diff options
Diffstat (limited to 'src')
5 files changed, 871 insertions, 625 deletions
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 82ad16cc624..ed5442442fe 100755 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -537,8 +537,12 @@ void GameObject::Update(uint32 diff) SetGoState(GO_STATE_READY); //any return here in case battleground traps + if (GetGOInfo()->flags & GO_FLAG_NODESPAWN) + return; } + loot.clear(); + if (GetOwnerGUID()) { if (Unit* owner = GetOwner()) @@ -550,6 +554,8 @@ void GameObject::Update(uint32 diff) return; } + SetLootState(GO_READY); + //burning flags in some battlegrounds, if you find better condition, just add it if (GetGOInfo()->IsDespawnAtAction() || GetGoAnimProgress() > 0) { @@ -558,9 +564,6 @@ void GameObject::Update(uint32 diff) SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags); } - loot.clear(); - SetLootState(GO_READY); - if (!m_respawnDelayTime) return; diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_ignis.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_ignis.cpp index bc593f70676..8a60dfd0e96 100644 --- a/src/server/scripts/Northrend/Ulduar/ulduar/boss_ignis.cpp +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_ignis.cpp @@ -17,7 +17,6 @@ #include "ScriptPCH.h" #include "ulduar.h" -#include "SpellAuraEffects.h" enum Yells { diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_razorscale.cpp index f510408b566..3690f9cd7fb 100644 --- a/src/server/scripts/Northrend/Ulduar/ulduar/boss_razorscale.cpp +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_razorscale.cpp @@ -1,819 +1,1024 @@ /* - * 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/>. - */ - -//TODO: Harpoon event is automated needs to be checked - -/* ScriptData -SDName: Razorscale -SDAuthor: PrinceCreed -SD%Complete: 100 -EndScriptData */ +* 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/>. +*/ + +//TODO: Harpoon chain from 62505 should not get removed when other chain is applied #include "ScriptPCH.h" #include "ulduar.h" enum Says { - SAY_GREET = -1603260, - SAY_GROUND_PHASE = -1603261, - SAY_AGGRO_1 = -1603262, - SAY_AGGRO_2 = -1603263, - SAY_AGGRO_3 = -1603264, - SAY_TURRETS = -1603265, - EMOTE_HARPOON = -1603266, - EMOTE_BREATH = -1603267, - EMOTE_PERMA = -1603268, + SAY_GREET = -1603260, + SAY_GROUND_PHASE = -1603261, + SAY_AGGRO_1 = -1603262, + SAY_AGGRO_2 = -1603263, + SAY_AGGRO_3 = -1603264, + SAY_TURRETS = -1603265, + EMOTE_HARPOON = -1603266, + EMOTE_BREATH = -1603267, + EMOTE_PERMA = -1603268, }; -#define GOSSIP_ITEM_1 "Activate Harpoones!" - enum Spells { - SPELL_FLAMEBUFFET = 64016, - SPELL_FIREBALL = 62796, - SPELL_FLAME_GROUND = 64709, - SPELL_WINGBUFFET = 62666, - SPELL_FLAMEBREATH = 63317, - SPELL_FUSEARMOR = 64771, - SPELL_DEVOURING_FLAME = 63236, - SPELL_HARPOON = 54933, - SPELL_FLAMED = 62696, - SPELL_STUN = 9032, - SPELL_BERSERK = 47008 + SPELL_FLAMEBUFFET = 64016, + SPELL_FIREBALL = 62796, + SPELL_FLAME_GROUND = 64734, + SPELL_WINGBUFFET = 62666, + SPELL_FLAMEBREATH = 63317, + SPELL_FUSEARMOR = 64771, + SPELL_FLAMED = 62696, + SPELL_STUN = 9032, + SPELL_BERSERK = 47008, + // Additonal Spells + // Devouring Flame Spells + SPELL_DEVOURING_FLAME = 63308, + SPELL_DEVOURING_FLAME_DAMAGE = 64704, + SPELL_DEVOURING_FLAME_TRIGGER = 64709, + // HarpoonSpells + SPELL_HARPOON_TRIGGER = 62505, + SPELL_HARPOON_SHOT_1 = 63658, + SPELL_HARPOON_SHOT_2 = 63657, + SPELL_HARPOON_SHOT_3 = 63659, + SPELL_HARPOON_SHOT_4 = 63524, }; -const Position PosHarpoon[4] = +enum NPC { -{594.317f, -136.953f, 391.517f, 4.544f}, -{577.449f, -136.953f, 391.517f, 4.877f}, -{607.726f, -146.857f, 391.517f, 4.041f}, -{561.449f, -146.857f, 391.517f, 5.426f} + NPC_DARK_RUNE_GUARDIAN = 33388, + NPC_DARK_RUNE_SENTINEL = 33846, + NPC_DARK_RUNE_WATCHER = 33453, + MOLE_MACHINE_TRIGGER = 33245, + NPC_COMMANDER = 33210, + NPC_ENGINEER = 33287, + NPC_DEFENDER = 33816, }; -const Position PosEngSpawn = {591.951f, -95.968f, 391.517f, 0}; +enum DarkRuneSpells +{ + // Dark Rune Watcher + SPELL_CHAIN_LIGHTNING = 64758, + SPELL_LIGHTNING_BOLT = 63809, + // Dark Rune Guardian + SPELL_STORMSTRIKE = 64757, + // Dark Rune Sentinel + SPELL_BATTLE_SHOUT = 46763, + SPELL_HEROIC_STRIKE = 45026, + SPELL_WHIRLWIND = 63807, +}; -const Position PosEngRepair[4] = +enum Actions { -{590.442f, -130.550f, 391.517f, 4.789f}, -{574.850f, -133.687f, 391.517f, 4.252f}, -{606.567f, -143.369f, 391.517f, 4.434f}, -{560.609f, -142.967f, 391.517f, 5.074f} + ACTION_EVENT_START = 1, + ACTION_GROUND_PHASE = 2, + ACTION_HARPOON_BUILD = 3, + ACTION_PLACE_BROKEN_HARPOON = 4, + ACTION_HARPOON_VISUAL = 5, + ACTION_HARPOON_CAST = 6, + ACTION_COMMANDER_RESET = 7, }; -const Position PosDefSpawn[4] = +enum Phases { -{600.75f, -104.850f, 391.517f, 0}, -{596.38f, -110.262f, 391.517f, 0}, -{566.47f, -103.633f, 391.517f, 0}, -{570.41f, -108.791f, 391.517f, 0} + PHASE_PERMAGROUND = 1, + PHASE_GROUND = 2, + PHASE_FLIGHT = 3, }; -const Position PosDefCombat[4] = +enum Events { -{614.975f, -155.138f, 391.517f, 4.154f}, -{609.814f, -204.968f, 391.517f, 5.385f}, -{563.531f, -201.557f, 391.517f, 4.108f}, -{560.231f, -153.677f, 391.517f, 5.403f} + EVENT_BERSERK = 1, + EVENT_BREATH = 2, + EVENT_BUFFET = 3, + EVENT_FIREBALL = 5, + EVENT_FLIGHT = 6, + EVENT_DEVOURING = 7, + EVENT_FLAME = 8, + EVENT_LAND = 9, + EVENT_GROUND = 10, + EVENT_FUSE = 11, + EVENT_SUMMON = 12, + // Razorscale Controller + EVENT_BUILD_HARPOON_1 = 13, + EVENT_BUILD_HARPOON_2 = 14, + EVENT_BUILD_HARPOON_3 = 15, + EVENT_BUILD_HARPOON_4 = 16, }; -const Position RazorFlight = {588.050f, -251.191f, 470.536f, 1.605f}; -const Position RazorGround = {586.966f, -175.534f, 391.517f, 1.692f}; +#define GROUND_Z 391.517f +#define GOSSIP_ITEM_1 "Activate Harpoons!" +#define DATA_QUICK_SHAVE 29192921 // 2919, 2921 are achievement IDs -enum Mobs +const Position PosEngRepair[4] = { - RAZORSCALE = 33186,// ?? why not use instance? - NPC_DARK_RUNE_GUARDIAN = 33388, - NPC_DARK_RUNE_SENTINEL = 33846, - NPC_DARK_RUNE_WATCHER = 33453, - MOLE_MACHINE_TRIGGER = 33245, - NPC_COMMANDER = 33210, - NPC_ENGINEER = 33287, - NPC_DEFENDER = 33816, - NPC_HARPOON = 33184, - GOB_MOLE_MACHINE = 194316 + { 590.442f, -130.550f, GROUND_Z, 4.789f }, + { 574.850f, -133.687f, GROUND_Z, 4.252f }, + { 606.567f, -143.369f, GROUND_Z, 4.434f }, + { 560.609f, -142.967f, GROUND_Z, 5.074f }, }; -enum DarkRuneSpells +const Position PosDefSpawn[4] = { - // Dark Rune Watcher - SPELL_CHAIN_LIGHTNING = 64758, - SPELL_LIGHTNING_BOLT = 63809, - - // Dark Rune Guardian - SPELL_STORMSTRIKE = 64757, - - // Dark Rune Sentinel - SPELL_BATTLE_SHOUT = 46763, - SPELL_HEROIC_STRIKE = 45026, - SPELL_WHIRLWIND = 63807, + { 600.75f, -104.850f, GROUND_Z, 0 }, + { 596.38f, -110.262f, GROUND_Z, 0 }, + { 566.47f, -103.633f, GROUND_Z, 0 }, + { 570.41f, -108.791f, GROUND_Z, 0 }, }; -#define ACHIEVEMENT_QUICK_SHAVE RAID_MODE(2919, 2921) - -#define ACTION_EVENT_START 1 -#define ACTION_GROUND_PHASE 2 - -enum Phases +const Position PosDefCombat[4] = { - PHASE_NULL, - PHASE_PERMAGROUND, - PHASE_GROUND, - PHASE_FLIGHT + { 614.975f, -155.138f, GROUND_Z, 4.154f }, + { 609.814f, -204.968f, GROUND_Z, 5.385f }, + { 563.531f, -201.557f, GROUND_Z, 4.108f }, + { 560.231f, -153.677f, GROUND_Z, 5.403f }, }; -enum Events +const Position PosHarpoon[4] = { - EVENT_NONE, - EVENT_BERSERK, - EVENT_BREATH, - EVENT_BUFFET, - EVENT_HARPOON, - EVENT_FIREBALL, - EVENT_FLIGHT, - EVENT_DEVOURING, - EVENT_FLAME, - EVENT_LAND, - EVENT_GROUND, - EVENT_FUSE, - EVENT_SUMMON + { 571.901f, -136.554f, GROUND_Z, 0 }, + { 589.450f, -134.888f, GROUND_Z, 0 }, + { 559.119f, -140.505f, GROUND_Z, 0 }, + { 606.229f, -136.721f, GROUND_Z, 0 }, }; -class boss_razorscale : public CreatureScript -{ -public: - boss_razorscale() : CreatureScript("boss_razorscale") { } +const Position RazorFlight = { 588.050f, -251.191f, 470.536f, 1.498f }; +const Position RazorGround = { 586.966f, -175.534f, GROUND_Z, 4.682f }; +const Position PosEngSpawn = { 591.951f, -95.9680f, GROUND_Z, 0.000f }; - CreatureAI* GetAI(Creature* pCreature) const - { - return new boss_razorscaleAI (pCreature); - } +class boss_razorscale_controller : public CreatureScript +{ + public: + boss_razorscale_controller() : CreatureScript("boss_razorscale_controller") { } - struct boss_razorscaleAI : public BossAI - { - boss_razorscaleAI(Creature *pCreature) : BossAI(pCreature, TYPE_RAZORSCALE), phase(PHASE_NULL) + struct boss_razorscale_controllerAI : public BossAI { - // Do not let Razorscale be affected by Battle Shout buff - me->ApplySpellImmune(0, IMMUNITY_ID, (SPELL_BATTLE_SHOUT), true); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); - me->ApplySpellImmune(0, IMMUNITY_ID, 49560, true); // Death Grip - } + boss_razorscale_controllerAI(Creature* creature) : BossAI(creature, DATA_RAZORSCALE_CONTROL) + { + me->SetDisplayId(me->GetCreatureInfo()->Modelid2); + } + + void Reset() + { + _Reset(); + me->SetReactState(REACT_PASSIVE); + } + + void SpellHit(Unit* /*caster*/, SpellEntry const* spell) + { + switch (spell->Id) + { + case SPELL_FLAMED: + if (GameObject* Harpoon1 = ObjectAccessor::GetGameObject(*me, instance->GetData64(GO_RAZOR_HARPOON_1))) + Harpoon1->RemoveFromWorld(); + if (GameObject* Harpoon2 = ObjectAccessor::GetGameObject(*me, instance->GetData64(GO_RAZOR_HARPOON_2))) + Harpoon2->RemoveFromWorld(); + if (GameObject* Harpoon3 = ObjectAccessor::GetGameObject(*me, instance->GetData64(GO_RAZOR_HARPOON_3))) + Harpoon3->RemoveFromWorld(); + if (GameObject* Harpoon4 = ObjectAccessor::GetGameObject(*me, instance->GetData64(GO_RAZOR_HARPOON_4))) + Harpoon4->RemoveFromWorld(); + me->AI()->DoAction(ACTION_HARPOON_BUILD); + me->AI()->DoAction(ACTION_PLACE_BROKEN_HARPOON); + break; + case SPELL_HARPOON_SHOT_1: + case SPELL_HARPOON_SHOT_2: + case SPELL_HARPOON_SHOT_3: + case SPELL_HARPOON_SHOT_4: + DoCast(SPELL_HARPOON_TRIGGER); + break; + } + } - Phases phase; + void JustDied(Unit* /*who*/) + { + _JustDied(); + } - uint32 EnrageTimer; - uint32 FlyCount; + void DoAction(int32 const action) + { + if (instance->GetBossState(TYPE_RAZORSCALE) != IN_PROGRESS) + return; - Creature* Harpoon[4]; - bool PermaGround; - bool Enraged; + switch (action) + { + case ACTION_HARPOON_BUILD: + events.ScheduleEvent(EVENT_BUILD_HARPOON_1, 50000); + if (me->GetMap()->GetSpawnMode() == RAID_DIFFICULTY_25MAN_NORMAL) + events.ScheduleEvent(EVENT_BUILD_HARPOON_3, 90000); + break; + case ACTION_PLACE_BROKEN_HARPOON: + for (uint8 n = 0; n < RAID_MODE(2,4); n++) + me->SummonGameObject(GO_RAZOR_BROKEN_HARPOON, PosHarpoon[n].GetPositionX(), PosHarpoon[n].GetPositionY(), PosHarpoon[n].GetPositionZ(), 2.286f, 0, 0, 0, 0, 180000); + break; + } + } - void Reset() + void UpdateAI(uint32 const Diff) + { + events.Update(Diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_BUILD_HARPOON_1: + DoScriptText(EMOTE_HARPOON, me); + if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_1, PosHarpoon[0].GetPositionX(), PosHarpoon[0].GetPositionY(), PosHarpoon[0].GetPositionZ(), 4.790f, 0.0f, 0.0f, 0.0f, 0.0f, me->GetRespawnTime())) + { + if (GameObject* BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) //only nearest broken harpoon + BrokenHarpoon->RemoveFromWorld(); + events.ScheduleEvent(EVENT_BUILD_HARPOON_2, 20000); + events.CancelEvent(EVENT_BUILD_HARPOON_1); + } + return; + case EVENT_BUILD_HARPOON_2: + DoScriptText(EMOTE_HARPOON, me); + if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_2, PosHarpoon[1].GetPositionX(), PosHarpoon[1].GetPositionY(), PosHarpoon[1].GetPositionZ(), 4.659f, 0, 0, 0, 0, me->GetRespawnTime())) + { + if (GameObject* BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) + BrokenHarpoon->RemoveFromWorld(); + events.CancelEvent(EVENT_BUILD_HARPOON_2); + } + return; + case EVENT_BUILD_HARPOON_3: + DoScriptText(EMOTE_HARPOON, me); + if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_3, PosHarpoon[2].GetPositionX(), PosHarpoon[2].GetPositionY(), PosHarpoon[2].GetPositionZ(), 5.382f, 0, 0, 0, 0, me->GetRespawnTime())) + { + if (GameObject* BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) + BrokenHarpoon->RemoveFromWorld(); + events.ScheduleEvent(EVENT_BUILD_HARPOON_4, 20000); + events.CancelEvent(EVENT_BUILD_HARPOON_3); + } + return; + case EVENT_BUILD_HARPOON_4: + DoScriptText(EMOTE_HARPOON, me); + if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_4, PosHarpoon[3].GetPositionX(), PosHarpoon[3].GetPositionY(), PosHarpoon[3].GetPositionZ(), 4.266f, 0, 0, 0, 0, me->GetRespawnTime())) + { + if (GameObject* BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) + BrokenHarpoon->RemoveFromWorld(); + events.CancelEvent(EVENT_BUILD_HARPOON_4); + } + return; + } + } + } + }; + + CreatureAI* GetAI(Creature* creature) const { - _Reset(); - me->SetFlying(true); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_PASSIVE); - PermaGround = false; + return new boss_razorscale_controllerAI(creature); } +}; - void EnterCombat(Unit* /*who*/) +class go_razorscale_harpoon : public GameObjectScript +{ + public: + go_razorscale_harpoon() : GameObjectScript("go_razorscale_harpoon") {} + + bool OnGossipHello(Player* player, GameObject* go) { - _EnterCombat(); - for (uint8 n = 0; n < RAID_MODE(2,4); ++n) - Harpoon[n] = me->SummonCreature(NPC_HARPOON, PosHarpoon[n], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 0); - me->SetSpeed(MOVE_FLIGHT, 3.0f, true); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_PASSIVE); - phase = PHASE_GROUND; - events.SetPhase(PHASE_GROUND); - FlyCount = 0; - EnrageTimer = 15*60*1000; // Enrage in 15 min - Enraged = false; - events.ScheduleEvent(EVENT_FLIGHT, 0, 0, PHASE_GROUND); + InstanceScript* instance = go->GetInstanceScript(); + if (Creature* razorscale = ObjectAccessor::GetCreature(*go, instance ? instance->GetData64(TYPE_RAZORSCALE) : 0)) + go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + return false; } +}; - void JustDied(Unit* /*Killer*/) - { - _JustDied(); +class boss_razorscale : public CreatureScript +{ + public: + boss_razorscale() : CreatureScript("boss_razorscale") { } - if (instance) + struct boss_razorscaleAI : public BossAI + { + boss_razorscaleAI(Creature* creature) : BossAI(creature, TYPE_RAZORSCALE) { - // A Quick Shave - if (FlyCount <= 2) - instance->DoCompleteAchievement(ACHIEVEMENT_QUICK_SHAVE); + // Do not let Razorscale be affected by Battle Shout buff + me->ApplySpellImmune(0, IMMUNITY_ID, (SPELL_BATTLE_SHOUT), true); + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); + me->ApplySpellImmune(0, IMMUNITY_ID, 49560, true); // Death Grip } - } - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; + Phases phase; - if (me->getVictim() && !me->getVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()) - me->Kill(me->getVictim()); + uint32 EnrageTimer; + uint8 FlyCount; + uint8 HarpoonCounter; + bool PermaGround; + bool Enraged; - events.Update(diff); + void Reset() + { + _Reset(); + me->SetFlying(true); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_PASSIVE); + PermaGround = false; + HarpoonCounter = 0; + if (Creature* commander = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(DATA_EXP_COMMANDER) : 0)) + commander->AI()->DoAction(ACTION_COMMANDER_RESET); + } - if (HealthBelowPct(50) && !PermaGround) - EnterPermaGround(); + void EnterCombat(Unit* /*who*/) + { + _EnterCombat(); + if (Creature* controller = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(DATA_RAZORSCALE_CONTROL) : 0)) + controller->AI()->DoAction(ACTION_HARPOON_BUILD); + me->SetSpeed(MOVE_FLIGHT, 3.0f, true); + me->SetReactState(REACT_PASSIVE); + phase = PHASE_GROUND; + events.SetPhase(PHASE_GROUND); + FlyCount = 0; + EnrageTimer = 600000; + Enraged = false; + events.ScheduleEvent(EVENT_FLIGHT, 0, 0, PHASE_GROUND); + } - if (EnrageTimer <= diff && !Enraged) + void JustDied(Unit* /*who*/) { - DoCast(me, SPELL_BERSERK); - Enraged = true; + _JustDied(); } - else EnrageTimer -= diff; - if (phase == PHASE_GROUND) + void SpellHit(Unit* /*caster*/, SpellEntry const* spell) { - while (uint32 eventId = events.ExecuteEvent()) + if (spell->Id == SPELL_HARPOON_TRIGGER) + ++HarpoonCounter; + } + + void MovementInform(uint32 type, uint32 id) + { + if (id == 1) { - switch(eventId) - { - case EVENT_FLIGHT: - phase = PHASE_FLIGHT; - events.SetPhase(PHASE_FLIGHT); - me->SetFlying(true); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_PASSIVE); - me->AttackStop(); - me->RemoveAllAuras(); - me->GetMotionMaster()->MovePoint(0,RazorFlight); - events.ScheduleEvent(EVENT_FIREBALL, 7000, 0, PHASE_FLIGHT); - events.ScheduleEvent(EVENT_DEVOURING, 10000, 0, PHASE_FLIGHT); - events.ScheduleEvent(EVENT_SUMMON, 5000, 0, PHASE_FLIGHT); - events.ScheduleEvent(EVENT_GROUND, 75000, 0, PHASE_FLIGHT); - ++FlyCount; - return; - case EVENT_LAND: - me->SetFlying(false); - me->NearTeleportTo(586.966f, -175.534f, 391.517f, 1.692f); - DoCast(me, SPELL_STUN, true); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (Creature *pCommander = me->GetCreature(*me, instance->GetData64(DATA_EXP_COMMANDER))) - pCommander->AI()->DoAction(ACTION_GROUND_PHASE); - events.ScheduleEvent(EVENT_HARPOON, 0, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_BREATH, 30000, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_BUFFET, 33000, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_FLIGHT, 35000, 0, PHASE_GROUND); - return; - case EVENT_HARPOON: - for (uint8 n = 0; n < RAID_MODE(2,4); ++n) - if (Harpoon[n]) - Harpoon[n]->CastSpell(me, SPELL_HARPOON, true); - events.ScheduleEvent(EVENT_HARPOON, 1500, 0, PHASE_GROUND); - return; - case EVENT_BREATH: - me->MonsterTextEmote(EMOTE_BREATH, 0, true); - DoCastAOE(SPELL_FLAMEBREATH); - events.CancelEvent(EVENT_HARPOON); - events.CancelEvent(EVENT_BREATH); - return; - case EVENT_BUFFET: - DoCastAOE(SPELL_WINGBUFFET); - for (uint8 n = 0; n < RAID_MODE(2,4); ++n) - if (Harpoon[n]) - Harpoon[n]->CastSpell(Harpoon[n], SPELL_FLAMED, true); - events.CancelEvent(EVENT_BUFFET); - return; - } + phase = PHASE_GROUND; + events.SetPhase(PHASE_GROUND); + events.ScheduleEvent(EVENT_LAND, 0, 0, PHASE_GROUND); } } - if (phase == PHASE_PERMAGROUND) + + uint32 GetData(uint32 type) { - while (uint32 eventId = events.ExecuteEvent()) + if (type == DATA_QUICK_SHAVE) + if (FlyCount <= 2) + return 1; + + return 0; + } + + void UpdateAI(uint32 const Diff) + { + if (!UpdateVictim()) + return; + + events.Update(Diff); + + if (HealthBelowPct(50) && !PermaGround) + EnterPermaGround(); + + if (EnrageTimer <= Diff && !Enraged) + { + DoCast(me, SPELL_BERSERK); + Enraged = true; + } + else + EnrageTimer -= Diff; + + if (HarpoonCounter == RAID_MODE(2, 4)) + { + HarpoonCounter = 0; + me->GetMotionMaster()->MovePoint(1, RazorGround); + } + + if (phase == PHASE_GROUND) { - switch(eventId) + while (uint32 eventId = events.ExecuteEvent()) { - case EVENT_FLAME: - DoCastAOE(SPELL_FLAMEBUFFET); - events.ScheduleEvent(EVENT_FLAME, 10000, 0, PHASE_PERMAGROUND); - return; - case EVENT_BREATH: - me->MonsterTextEmote(EMOTE_BREATH, 0, true); - DoCastVictim(SPELL_FLAMEBREATH); - events.ScheduleEvent(EVENT_BREATH, 20000, 0, PHASE_PERMAGROUND); - return; - case EVENT_FIREBALL: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) - DoCast(pTarget, SPELL_FIREBALL); - events.ScheduleEvent(EVENT_FIREBALL, 3000, 0, PHASE_PERMAGROUND); - return; - case EVENT_DEVOURING: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) - DoCast(pTarget, SPELL_DEVOURING_FLAME); - events.ScheduleEvent(EVENT_DEVOURING, 10000, 0, PHASE_PERMAGROUND); - return; - case EVENT_BUFFET: - DoCastAOE(SPELL_WINGBUFFET); - events.CancelEvent(EVENT_BUFFET); - return; - case EVENT_FUSE: - DoCastVictim(SPELL_FUSEARMOR); - events.ScheduleEvent(EVENT_FUSE, 10000, 0, PHASE_PERMAGROUND); - return; + switch (eventId) + { + case EVENT_FLIGHT: + phase = PHASE_FLIGHT; + events.SetPhase(PHASE_FLIGHT); + me->SetFlying(true); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + me->GetMotionMaster()->MovePoint(0, RazorFlight); + events.ScheduleEvent(EVENT_FIREBALL, 7000, 0, PHASE_FLIGHT); + events.ScheduleEvent(EVENT_DEVOURING, 10000, 0, PHASE_FLIGHT); + events.ScheduleEvent(EVENT_SUMMON, 5000, 0, PHASE_FLIGHT); + ++FlyCount; + return; + case EVENT_LAND: + me->SetFlying(false); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); + if (Creature* commander = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(DATA_EXP_COMMANDER) : 0)) + commander->AI()->DoAction(ACTION_GROUND_PHASE); + events.ScheduleEvent(EVENT_BREATH, 30000, 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_BUFFET, 33000, 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_FLIGHT, 35000, 0, PHASE_GROUND); + return; + case EVENT_BREATH: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); + me->RemoveAllAuras(); + me->SetReactState(REACT_AGGRESSIVE); + DoScriptText(EMOTE_BREATH, me, 0); + DoCastAOE(SPELL_FLAMEBREATH); + events.CancelEvent(EVENT_BREATH); + return; + case EVENT_BUFFET: + DoCastAOE(SPELL_WINGBUFFET); + if (Creature* controller = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(DATA_RAZORSCALE_CONTROL) : 0)) + controller->CastSpell(controller, SPELL_FLAMED, true); + events.CancelEvent(EVENT_BUFFET); + return; + } } } + if (phase == PHASE_PERMAGROUND) + { + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_FLAME: + DoCastAOE(SPELL_FLAMEBUFFET); + events.ScheduleEvent(EVENT_FLAME, 10000, 0, PHASE_PERMAGROUND); + return; + case EVENT_BREATH: + me->MonsterTextEmote(EMOTE_BREATH, 0, true); + DoCastVictim(SPELL_FLAMEBREATH); + events.ScheduleEvent(EVENT_BREATH, 20000, 0, PHASE_PERMAGROUND); + return; + case EVENT_FIREBALL: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true)) + DoCast(target, SPELL_FIREBALL); + events.ScheduleEvent(EVENT_FIREBALL, 3000, 0, PHASE_PERMAGROUND); + return; + case EVENT_DEVOURING: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true)) + DoCast(target, SPELL_DEVOURING_FLAME); + events.ScheduleEvent(EVENT_DEVOURING, 10000, 0, PHASE_PERMAGROUND); + return; + case EVENT_BUFFET: + DoCastAOE(SPELL_WINGBUFFET); + events.CancelEvent(EVENT_BUFFET); + return; + case EVENT_FUSE: + DoCast(me->getVictim(), SPELL_FUSEARMOR); + events.ScheduleEvent(EVENT_FUSE, 10000, 0, PHASE_PERMAGROUND); + return; + } + } - DoMeleeAttackIfReady(); - } - else - { - if (uint32 eventId = events.ExecuteEvent()) + DoMeleeAttackIfReady(); + } + else { - switch(eventId) + if (uint32 eventId = events.ExecuteEvent()) { - case EVENT_GROUND: - phase = PHASE_GROUND; - events.SetPhase(PHASE_GROUND); - if (Harpoon[0]) - Harpoon[0]->MonsterTextEmote(EMOTE_HARPOON, 0, true); - me->GetMotionMaster()->MovePoint(0,RazorGround); - events.ScheduleEvent(EVENT_LAND, 5500, 0, PHASE_GROUND); - return; - case EVENT_FIREBALL: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) - DoCast(pTarget, SPELL_FIREBALL); - events.ScheduleEvent(EVENT_FIREBALL, 3000, 0, PHASE_FLIGHT); - return; - case EVENT_DEVOURING: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) - DoCast(pTarget, SPELL_DEVOURING_FLAME); - events.ScheduleEvent(EVENT_DEVOURING, 10000, 0, PHASE_FLIGHT); - return; - case EVENT_SUMMON: - SummonAdds(); - events.ScheduleEvent(EVENT_SUMMON, 45000, 0, PHASE_FLIGHT); - return; + switch (eventId) + { + case EVENT_FIREBALL: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true)) + DoCast(target, SPELL_FIREBALL); + events.ScheduleEvent(EVENT_FIREBALL, 3000, 0, PHASE_FLIGHT); + return; + case EVENT_DEVOURING: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true)) + me->CastSpell(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), SPELL_DEVOURING_FLAME, true); + events.ScheduleEvent(EVENT_DEVOURING, 10000, 0, PHASE_FLIGHT); + return; + case EVENT_SUMMON: + SummonMoleMachines(); + events.ScheduleEvent(EVENT_SUMMON, 45000, 0, PHASE_FLIGHT); + return; + } } } } - } - void EnterPermaGround() - { - me->MonsterTextEmote(EMOTE_PERMA, 0, true); - phase = PHASE_PERMAGROUND; - events.SetPhase(PHASE_PERMAGROUND); - me->SetFlying(false); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveAurasDueToSpell(SPELL_STUN); - me->SetSpeed(MOVE_FLIGHT, 1.0f, true); - PermaGround = true; - DoCastAOE(SPELL_FLAMEBREATH); - events.ScheduleEvent(EVENT_FLAME, 15000, 0, PHASE_PERMAGROUND); - events.RescheduleEvent(EVENT_DEVOURING, 15000, 0, PHASE_PERMAGROUND); - events.RescheduleEvent(EVENT_BREATH, 20000, 0, PHASE_PERMAGROUND); - events.RescheduleEvent(EVENT_FIREBALL, 3000, 0, PHASE_PERMAGROUND); - events.RescheduleEvent(EVENT_DEVOURING, 6000, 0, PHASE_PERMAGROUND); - events.RescheduleEvent(EVENT_BUFFET, 2500, 0, PHASE_PERMAGROUND); - events.RescheduleEvent(EVENT_FUSE, 5000, 0, PHASE_PERMAGROUND); - } + void EnterPermaGround() + { + me->MonsterTextEmote(EMOTE_PERMA, 0, true); + phase = PHASE_PERMAGROUND; + events.SetPhase(PHASE_PERMAGROUND); + me->SetFlying(false); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveAurasDueToSpell(SPELL_HARPOON_TRIGGER); + me->SetSpeed(MOVE_FLIGHT, 1.0f, true); + PermaGround = true; + DoCastAOE(SPELL_FLAMEBREATH); + events.ScheduleEvent(EVENT_FLAME, 15000, 0, PHASE_PERMAGROUND); + events.RescheduleEvent(EVENT_DEVOURING, 15000, 0, PHASE_PERMAGROUND); + events.RescheduleEvent(EVENT_BREATH, 20000, 0, PHASE_PERMAGROUND); + events.RescheduleEvent(EVENT_FIREBALL, 3000, 0, PHASE_PERMAGROUND); + events.RescheduleEvent(EVENT_DEVOURING, 6000, 0, PHASE_PERMAGROUND); + events.RescheduleEvent(EVENT_BUFFET, 2500, 0, PHASE_PERMAGROUND); + events.RescheduleEvent(EVENT_FUSE, 5000, 0, PHASE_PERMAGROUND); + } - void SummonAdds() - { - // Adds will come in waves from mole machines. One mole can spawn a Dark Rune Watcher - // with 1-2 Guardians, or a lone Sentinel. Up to 4 mole machines can spawn adds at any given time. - uint8 random = urand(1,4); - for (uint8 i = 0; i < random; ++i) + void SummonMoleMachines() { - float x = float(irand(540, 640)); // Safe range is between 500 and 650 - float y = float(irand(-230, -195)); // Safe range is between -235 and -145 - float z = 391.5f; // Ground level - me->SummonCreature(MOLE_MACHINE_TRIGGER, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 10000); + // Adds will come in waves from mole machines. One mole can spawn a Dark Rune Watcher + // with 1-2 Guardians, or a lone Sentinel. Up to 4 mole machines can spawn adds at any given time. + uint8 random = urand(2, 4); + for (uint8 n = 0; n < random; n++) + { + float x = float(irand(540, 640)); // Safe range is between 500 and 650 + float y = float(irand(-230, -195)); // Safe range is between -235 and -145 + float z = GROUND_Z; // Ground level + me->SummonCreature(MOLE_MACHINE_TRIGGER, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 10000); + } } - } - void DoAction(const int32 action) - { - switch(action) + void DoAction(int32 const action) { - case ACTION_EVENT_START: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_AGGRESSIVE); - DoZoneInCombat(); - break; + switch (action) + { + case ACTION_EVENT_START: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + DoZoneInCombat(); + break; + } } - } - }; + }; + CreatureAI* GetAI(Creature* creature) const + { + return new boss_razorscaleAI(creature); + } }; -/*==================================================================================== -====================================================================================*/ - class npc_expedition_commander : public CreatureScript { -public: - npc_expedition_commander() : CreatureScript("npc_expedition_commander") { } - - bool OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) - { - pPlayer->PlayerTalkClass->ClearMenus(); - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - if (pPlayer) - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_expedition_commanderAI, (pCreature->AI()))->uiPhase = 1; - break; - } - return true; - } + public: + npc_expedition_commander() : CreatureScript("npc_expedition_commander") { } - bool OnGossipHello(Player* pPlayer, Creature* pCreature) - { - InstanceScript* pInstance = pCreature->GetInstanceScript(); - if (pInstance && pInstance->GetBossState(TYPE_RAZORSCALE) == NOT_STARTED && pPlayer) + struct npc_expedition_commanderAI : public ScriptedAI { - pPlayer->PrepareGossipMenu(pCreature); - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_1,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(13853, pCreature->GetGUID()); - } - else pPlayer->SEND_GOSSIP_MENU(13910, pCreature->GetGUID()); - - return true; - } + npc_expedition_commanderAI(Creature* creature) : ScriptedAI(creature) + { + instance = me->GetInstanceScript(); + Greet = false; + } - CreatureAI* GetAI(Creature* pCreature) const - { - return new npc_expedition_commanderAI (pCreature); - } + InstanceScript* instance; + std::list<uint64> summons; - struct npc_expedition_commanderAI : public ScriptedAI - { - npc_expedition_commanderAI(Creature* pCreature) : ScriptedAI(pCreature), summons(me) - { - pInstance = pCreature->GetInstanceScript(); - greet = false; - } + bool Greet; + uint32 AttackStartTimer; + uint8 Phase; + Creature* Engineer[4]; + Creature* Defender[4]; - InstanceScript* pInstance; - SummonList summons; + void Reset() + { + AttackStartTimer = 0; + Phase = 0; + Greet = false; + summons.clear(); + } - bool greet; - uint32 uiTimer; - uint8 uiPhase; - Creature* engineer[4]; - Creature* defender[4]; + void MoveInLineOfSight(Unit* who) + { + if (!Greet && me->IsWithinDistInMap(who, 10.0f) && who->GetTypeId() == TYPEID_PLAYER) + { + DoScriptText(SAY_GREET, me); + Greet = true; + } + } - void Reset() - { - uiTimer = 0; - uiPhase = 0; - greet = false; - } + void JustSummoned(Creature* summoned) + { + summons.push_back(summoned->GetGUID()); + } - void MoveInLineOfSight(Unit *who) - { - if (!greet && me->IsWithinDistInMap(who, 10.0f) && who->GetTypeId() == TYPEID_PLAYER) + void DoAction(int32 const action) { - DoScriptText(SAY_GREET, me); - greet = true; + switch (action) + { + case ACTION_GROUND_PHASE: + DoScriptText(SAY_GROUND_PHASE, me); + break; + case ACTION_COMMANDER_RESET: + summons.clear(); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + break; + } } - } - void JustSummoned(Creature *summon) - { - summons.Summon(summon); - } + void UpdateAI(uint32 const Diff) + { + if (AttackStartTimer <= Diff) + { + switch (Phase) + { + case 1: + instance->SetBossState(TYPE_RAZORSCALE, IN_PROGRESS); + summons.clear(); + AttackStartTimer = 1000; + Phase = 2; + break; + case 2: + for (uint8 n = 0; n < RAID_MODE(2, 4); n++) + { + Engineer[n] = me->SummonCreature(NPC_ENGINEER, PosEngSpawn, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); + Engineer[n]->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); + Engineer[n]->SetSpeed(MOVE_RUN, 0.5f); + Engineer[n]->SetHomePosition(PosEngRepair[n]); + Engineer[n]->GetMotionMaster()->MoveTargetedHome(); + } + Engineer[0]->MonsterYell(SAY_AGGRO_3, LANG_UNIVERSAL, 0); + Phase = 3; + AttackStartTimer = 14000; + break; + case 3: + for (uint8 n = 0; n < 4; n++) + { + Defender[n] = me->SummonCreature(NPC_DEFENDER, PosDefSpawn[n], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); + Defender[n]->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); + Defender[n]->SetHomePosition(PosDefCombat[n]); + Defender[n]->GetMotionMaster()->MoveTargetedHome(); + } + Phase = 4; + break; + case 4: + for (uint8 n = 0; n < RAID_MODE(2, 4); n++) + Engineer[n]->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USESTANDING); + for (uint8 n = 0; n < 4; ++n) + Defender[n]->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); + me->MonsterYell(SAY_AGGRO_2, LANG_UNIVERSAL, 0); + AttackStartTimer = 16000; + Phase = 5; + break; + case 5: + if (Creature* Razorscale = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(TYPE_RAZORSCALE) : 0)) + { + Razorscale->AI()->DoAction(ACTION_EVENT_START); + me->SetInCombatWith(Razorscale); + } + Engineer[0]->MonsterYell(SAY_AGGRO_1, LANG_UNIVERSAL, 0); + Phase = 6; + break; + } + } + else + AttackStartTimer -= Diff; + } + }; - void DoAction(const int32 action) + bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) { - switch(action) + player->PlayerTalkClass->ClearMenus(); + switch (action) { - case ACTION_GROUND_PHASE: - DoScriptText(SAY_GROUND_PHASE, me); + case GOSSIP_ACTION_INFO_DEF: + player->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_expedition_commanderAI, creature->AI())->Phase = 1; break; } + return true; } - void UpdateAI(const uint32 uiDiff) + bool OnGossipHello(Player* player, Creature* creature) { - ScriptedAI::UpdateAI(uiDiff); - if (uiTimer <= uiDiff) + InstanceScript* instance = creature->GetInstanceScript(); + if (instance && instance->GetBossState(TYPE_RAZORSCALE) == NOT_STARTED) { - switch(uiPhase) - { - case 1: - pInstance->SetBossState(TYPE_RAZORSCALE, IN_PROGRESS); - summons.DespawnAll(); - uiTimer = 1000; - uiPhase = 2; - break; - case 2: - for (uint8 n = 0; n < RAID_MODE(2,4); ++n) - { - engineer[n] = me->SummonCreature(NPC_ENGINEER, PosEngSpawn, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); - engineer[n]->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); - engineer[n]->SetSpeed(MOVE_RUN, 0.5f); - engineer[n]->SetHomePosition(PosEngRepair[n]); - engineer[n]->GetMotionMaster()->MoveTargetedHome(); - } - engineer[0]->MonsterYell(SAY_AGGRO_3, LANG_UNIVERSAL, 0); - uiPhase = 3; - uiTimer = 14000; - break; - case 3: - for (uint8 n = 0; n < 4; ++n) - { - defender[n] = me->SummonCreature(NPC_DEFENDER, PosDefSpawn[n], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); - defender[n] ->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); - defender[n] ->SetHomePosition(PosDefCombat[n]); - defender[n] ->GetMotionMaster()->MoveTargetedHome(); - } - uiPhase = 4; - break; - case 4: - for (uint8 n = 0; n < RAID_MODE(2,4); ++n) - engineer[n]->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USESTANDING); - for (uint8 n = 0; n < 4; ++n) - defender[n]->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); - me->MonsterYell(SAY_AGGRO_2, LANG_UNIVERSAL, 0); - uiTimer = 16000; - uiPhase = 5; - break; - case 5: - if (Creature *pRazorscale = me->GetCreature(*me, pInstance->GetData64(TYPE_RAZORSCALE))) - pRazorscale->AI()->DoAction(ACTION_EVENT_START); - engineer[0]->MonsterYell(SAY_AGGRO_1, LANG_UNIVERSAL, 0); - uiPhase = 6; - break; - } + player->PrepareGossipMenu(creature); + + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + player->SEND_GOSSIP_MENU(13853, creature->GetGUID()); } - else uiTimer -= uiDiff; + else + player->SEND_GOSSIP_MENU(13910, creature->GetGUID()); + + return true; } - }; + CreatureAI* GetAI(Creature* creature) const + { + return new npc_expedition_commanderAI(creature); + } }; class npc_mole_machine_trigger : public CreatureScript { -public: - npc_mole_machine_trigger() : CreatureScript("npc_mole_machine_trigger") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new npc_mole_machine_triggerAI (pCreature); - } + public: + npc_mole_machine_trigger() : CreatureScript("npc_mole_machine_trigger") { } - struct npc_mole_machine_triggerAI : public Scripted_NoMovementAI - { - npc_mole_machine_triggerAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) + struct npc_mole_machine_triggerAI : public Scripted_NoMovementAI { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); - me->SetVisible(false); - } - - GameObject* MoleMachine; - uint32 SummonTimer; + npc_mole_machine_triggerAI(Creature* creature) : Scripted_NoMovementAI(creature) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); + me->SetVisible(false); + } - void Reset() - { - MoleMachine = me->SummonGameObject(GOB_MOLE_MACHINE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), - float(urand(0, 6)), 0, 0, 0, 0, 300); - if (MoleMachine) - MoleMachine->SetGoState(GO_STATE_ACTIVE); - SummonTimer = 6000; - } + uint32 SummonTimer; - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; + void Reset() + { + if (GameObject* MoleMachine = me->SummonGameObject(GO_MOLE_MACHINE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), float(urand(0, 6)), 0, 0, 0, 0, 300)) + MoleMachine->SetGoState(GO_STATE_ACTIVE); + SummonTimer = 6000; + } - if (SummonTimer <= uiDiff) + void UpdateAI(uint32 const Diff) { - float x = me->GetPositionX(); - float y = me->GetPositionY(); - float z = me->GetPositionZ(); + if (!UpdateVictim()) + return; - // One mole can spawn a Dark Rune Watcher with 1-2 Guardians, or a lone Sentinel - if (!(rand()%2)) + if (SummonTimer <= Diff) { - me->SummonCreature(NPC_DARK_RUNE_WATCHER, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); - uint8 random = urand(1,2); - for (uint8 i = 0; i < random; ++i) - me->SummonCreature(NPC_DARK_RUNE_GUARDIAN, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); + float x = me->GetPositionX(); + float y = me->GetPositionY(); + float z = me->GetPositionZ(); + + // One mole can spawn a Dark Rune Watcher with 1-2 Guardians, or a lone Sentinel + uint8 id = urand(0, 1); + if (id) + { + me->SummonCreature(NPC_DARK_RUNE_WATCHER, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); + for (uint8 n = 0; n < urand(1, 2); n++) + me->SummonCreature(NPC_DARK_RUNE_GUARDIAN, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); + } + else + me->SummonCreature(NPC_DARK_RUNE_SENTINEL, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); + + SummonTimer = 15000; } - else me->SummonCreature(NPC_DARK_RUNE_SENTINEL, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); + else + SummonTimer -= Diff; + } - SummonTimer = 15000; + void JustSummoned(Creature* summoned) + { + summoned->AI()->DoZoneInCombat(); } - else SummonTimer -= uiDiff; - } + }; - void JustSummoned(Creature *summon) + CreatureAI* GetAI(Creature* creature) const { - summon->AI()->DoZoneInCombat(); + return new npc_mole_machine_triggerAI(creature); } - }; - }; class npc_devouring_flame : public CreatureScript { -public: - npc_devouring_flame() : CreatureScript("npc_devouring_flame") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new npc_devouring_flameAI (pCreature); - } + public: + npc_devouring_flame() : CreatureScript("npc_devouring_flame") { } - struct npc_devouring_flameAI : public Scripted_NoMovementAI - { - npc_devouring_flameAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) + struct npc_devouring_flameAI : public Scripted_NoMovementAI { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); - me->SetDisplayId(11686); - } + npc_devouring_flameAI(Creature* creature) : Scripted_NoMovementAI(creature) + { + me->SetDisplayId(me->GetCreatureInfo()->Modelid2); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); + } + + void Reset() + { + DoCast(SPELL_FLAME_GROUND); + } + }; - void Reset() + CreatureAI* GetAI(Creature* creature) const { - DoCast(me, SPELL_FLAME_GROUND); + return new npc_devouring_flameAI(creature); } - }; - }; class npc_darkrune_watcher : public CreatureScript { -public: - npc_darkrune_watcher() : CreatureScript("npc_darkrune_watcher") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new npc_darkrune_watcherAI (pCreature); - } + public: + npc_darkrune_watcher() : CreatureScript("npc_darkrune_watcher") { } - struct npc_darkrune_watcherAI : public ScriptedAI - { - npc_darkrune_watcherAI(Creature *pCreature) : ScriptedAI(pCreature) + struct npc_darkrune_watcherAI : public ScriptedAI { - pInstance = pCreature->GetInstanceScript(); - } - - InstanceScript *pInstance; - - uint32 ChainTimer; - uint32 LightTimer; + npc_darkrune_watcherAI(Creature* creature) : ScriptedAI(creature) + { + instance = me->GetInstanceScript(); + } - void Reset() - { - ChainTimer = urand(10000, 15000); - LightTimer = urand(1000, 3000); - } + InstanceScript* instance; - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; + uint32 ChainTimer; + uint32 LightTimer; - if (ChainTimer <= uiDiff) + void Reset() { - DoCastVictim(SPELL_CHAIN_LIGHTNING); ChainTimer = urand(10000, 15000); + LightTimer = urand(1000, 3000); } - else ChainTimer -= uiDiff; - if (LightTimer <= uiDiff) + void UpdateAI(uint32 const Diff) { - DoCastVictim(SPELL_LIGHTNING_BOLT); - LightTimer = urand(5000, 7000); + if (!UpdateVictim()) + return; + + if (ChainTimer <= Diff) + { + DoCast(me->getVictim(), SPELL_CHAIN_LIGHTNING); + ChainTimer = urand(10000, 15000); + } + else + ChainTimer -= Diff; + + if (LightTimer <= Diff) + { + DoCastVictim(SPELL_LIGHTNING_BOLT); + LightTimer = urand(5000, 7000); + } + else + LightTimer -= Diff; + + DoMeleeAttackIfReady(); } - else LightTimer -= uiDiff; + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const + { + return new npc_darkrune_watcherAI(creature); } - }; - }; class npc_darkrune_guardian : public CreatureScript { -public: - npc_darkrune_guardian() : CreatureScript("npc_darkrune_guardian") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new npc_darkrune_guardianAI (pCreature); - } + public: + npc_darkrune_guardian() : CreatureScript("npc_darkrune_guardian") { } - struct npc_darkrune_guardianAI : public ScriptedAI - { - npc_darkrune_guardianAI(Creature *pCreature) : ScriptedAI(pCreature) + struct npc_darkrune_guardianAI : public ScriptedAI { - pInstance = pCreature->GetInstanceScript(); - } - - InstanceScript *pInstance; + npc_darkrune_guardianAI(Creature* creature) : ScriptedAI(creature) + { + instance = me->GetInstanceScript(); + } - uint32 StormTimer; + InstanceScript* instance; - void Reset() - { - StormTimer = urand(3000, 6000); - } + uint32 StormTimer; - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; + void Reset() + { + StormTimer = urand(3000, 6000); + } - if (StormTimer <= uiDiff) + void UpdateAI(uint32 const Diff) { - DoCastVictim(SPELL_STORMSTRIKE); - StormTimer = urand(4000, 8000); + if (!UpdateVictim()) + return; + + if (StormTimer <= Diff) + { + DoCast(me->getVictim(), SPELL_STORMSTRIKE); + StormTimer = urand(4000, 8000); + } + else + StormTimer -= Diff; + + DoMeleeAttackIfReady(); } - else StormTimer -= uiDiff; + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const + { + return new npc_darkrune_guardianAI(creature); } - }; - }; class npc_darkrune_sentinel : public CreatureScript { -public: - npc_darkrune_sentinel() : CreatureScript("npc_darkrune_sentinel") { } + public: + npc_darkrune_sentinel() : CreatureScript("npc_darkrune_sentinel") { } - CreatureAI* GetAI(Creature* pCreature) const - { - return new npc_darkrune_sentinelAI (pCreature); - } - - struct npc_darkrune_sentinelAI : public ScriptedAI - { - npc_darkrune_sentinelAI(Creature *pCreature) : ScriptedAI(pCreature) + struct npc_darkrune_sentinelAI : public ScriptedAI { - pInstance = pCreature->GetInstanceScript(); - } + npc_darkrune_sentinelAI(Creature* creature) : ScriptedAI(creature) + { + instance = me->GetInstanceScript(); + } + + InstanceScript* instance; + + uint32 HeroicTimer; + uint32 WhirlTimer; + uint32 ShoutTimer; + + void Reset() + { + HeroicTimer = urand(4000, 8000); + WhirlTimer = urand(20000, 25000); + ShoutTimer = urand(15000, 30000); + } + + void UpdateAI(uint32 const Diff) + { + if (!UpdateVictim()) + return; + + if (HeroicTimer <= Diff) + { + DoCast(me->getVictim(), SPELL_HEROIC_STRIKE); + HeroicTimer = urand(4000, 6000); + } + else + HeroicTimer -= Diff; + + if (WhirlTimer <= Diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND); + WhirlTimer = urand(20000, 25000); + } + else + WhirlTimer -= Diff; - InstanceScript *pInstance; + if (ShoutTimer <= Diff) + { + DoCast(me, SPELL_BATTLE_SHOUT); + ShoutTimer = urand(30000, 40000); + } + else + ShoutTimer -= Diff; - uint32 HeroicTimer; - uint32 WhirlTimer; - uint32 ShoutTimer; + DoMeleeAttackIfReady(); + } + }; - void Reset() + CreatureAI* GetAI(Creature* creature) const { - HeroicTimer = urand(4000, 8000); - WhirlTimer = urand(20000, 25000); - ShoutTimer = urand(15000, 30000); + return new npc_darkrune_sentinelAI(creature); } +}; - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; +class spell_razorscale_devouring_flame : public SpellScriptLoader +{ + public: + spell_razorscale_devouring_flame() : SpellScriptLoader("spell_razorscale_devouring_flame") { } - if (HeroicTimer <= uiDiff) - { - DoCastVictim(SPELL_HEROIC_STRIKE); - HeroicTimer = urand(4000, 6000); - } - else HeroicTimer -= uiDiff; + class spell_razorscale_devouring_flame_SpellScript : public SpellScript + { + PrepareSpellScript(spell_razorscale_devouring_flame_SpellScript); - if (WhirlTimer <= uiDiff) + void HandleSummon(SpellEffIndex effIndex) { - DoCastVictim(SPELL_WHIRLWIND); - WhirlTimer = urand(20000, 25000); + PreventHitDefaultEffect(effIndex); + Unit* caster = GetCaster(); + uint32 entry = uint32(GetSpellInfo()->EffectMiscValue[effIndex]); + WorldLocation* summonLocation = GetTargetDest(); + if (!caster || !summonLocation) + return; + + caster->SummonCreature(entry, summonLocation->GetPositionX(), summonLocation->GetPositionY(), GROUND_Z, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 20000); } - else WhirlTimer -= uiDiff; - if (ShoutTimer <= uiDiff) + void Register() { - DoCast(me, SPELL_BATTLE_SHOUT); - ShoutTimer = urand(30000, 40000); + OnEffect += SpellEffectFn(spell_razorscale_devouring_flame_SpellScript::HandleSummon, EFFECT_0, SPELL_EFFECT_SUMMON); } - else ShoutTimer -= uiDiff; + }; - DoMeleeAttackIfReady(); + SpellScript* GetSpellScript() const + { + return new spell_razorscale_devouring_flame_SpellScript(); } - }; +}; +class achievement_quick_shave : public AchievementCriteriaScript +{ + public: + achievement_quick_shave() : AchievementCriteriaScript("achievement_quick_shave") { } + + bool OnCheck(Player* /*source*/, Unit* target) + { + if (target) + if (Creature* razorscale = target->ToCreature()) + if (razorscale->AI()->GetData(DATA_QUICK_SHAVE)) + return true; + + return false; + } }; void AddSC_boss_razorscale() { + new boss_razorscale_controller(); + new go_razorscale_harpoon(); new boss_razorscale(); new npc_expedition_commander(); new npc_mole_machine_trigger(); @@ -821,4 +1026,6 @@ void AddSC_boss_razorscale() new npc_darkrune_watcher(); new npc_darkrune_guardian(); new npc_darkrune_sentinel(); + new spell_razorscale_devouring_flame(); + new achievement_quick_shave(); }
\ No newline at end of file diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/instance_ulduar.cpp index 26ffd7cff70..1373e3e7208 100644 --- a/src/server/scripts/Northrend/Ulduar/ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/ulduar/instance_ulduar.cpp @@ -45,6 +45,8 @@ public: uint64 uiLeviathanGUID; uint64 uiIgnisGUID; uint64 uiRazorscaleGUID; + uint64 uiRazorscaleController; + uint64 uiRazorHarpoonGUIDs[3]; uint64 uiExpCommanderGUID; uint64 uiXT002GUID; uint64 uiAssemblyGUIDs[3]; @@ -77,6 +79,7 @@ public: LoadDoorData(doorData); uiIgnisGUID = 0; uiRazorscaleGUID = 0; + uiRazorscaleController = 0; uiExpCommanderGUID = 0; uiXT002GUID = 0; uiKologarnGUID = 0; @@ -100,8 +103,9 @@ public: uiVezaxDoorGUID = 0; flag = 0; - memset(&uiEncounter, 0, sizeof(uiEncounter)); - memset(&uiAssemblyGUIDs, 0, sizeof(uiAssemblyGUIDs)); + memset(uiEncounter, 0, sizeof(uiEncounter)); + memset(uiAssemblyGUIDs, 0, sizeof(uiAssemblyGUIDs)); + memset(uiRazorHarpoonGUIDs, 0, sizeof(uiRazorHarpoonGUIDs)); } bool IsEncounterInProgress() const @@ -128,6 +132,9 @@ public: case NPC_RAZORSCALE: uiRazorscaleGUID = creature->GetGUID(); break; + case NPC_RAZORSCALE_CONTROLLER: + uiRazorscaleController = creature->GetGUID(); + break; case NPC_EXPEDITION_COMMANDER: uiExpCommanderGUID = creature->GetGUID(); return; @@ -235,6 +242,18 @@ public: uiVezaxDoorGUID = go->GetGUID(); HandleGameObject(NULL, false, go); break; + case GO_RAZOR_HARPOON_1: + uiRazorHarpoonGUIDs[0] = go->GetGUID(); + break; + case GO_RAZOR_HARPOON_2: + uiRazorHarpoonGUIDs[1] = go->GetGUID(); + break; + case GO_RAZOR_HARPOON_3: + uiRazorHarpoonGUIDs[2] = go->GetGUID(); + break; + case GO_RAZOR_HARPOON_4: + uiRazorHarpoonGUIDs[3] = go->GetGUID(); + break; } } @@ -369,6 +388,7 @@ public: case TYPE_LEVIATHAN: return uiLeviathanGUID; case TYPE_IGNIS: return uiIgnisGUID; case TYPE_RAZORSCALE: return uiRazorscaleGUID; + case DATA_RAZORSCALE_CONTROL: return uiRazorscaleController; case TYPE_XT002: return uiXT002GUID; case TYPE_KOLOGARN: return uiKologarnGUID; case DATA_LEFT_ARM: return uiLeftArmGUID; @@ -384,6 +404,10 @@ public: // razorscale expedition commander case DATA_EXP_COMMANDER: return uiExpCommanderGUID; + case GO_RAZOR_HARPOON_1: return uiRazorHarpoonGUIDs[0]; + case GO_RAZOR_HARPOON_2: return uiRazorHarpoonGUIDs[1]; + case GO_RAZOR_HARPOON_3: return uiRazorHarpoonGUIDs[2]; + case GO_RAZOR_HARPOON_4: return uiRazorHarpoonGUIDs[3]; // Assembly of Iron case DATA_STEELBREAKER: return uiAssemblyGUIDs[0]; case DATA_MOLGEIM: return uiAssemblyGUIDs[1]; @@ -466,6 +490,7 @@ public: }; + void AddSC_instance_ulduar() { new instance_ulduar(); diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h index 15276562197..5015cb0df4f 100644 --- a/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h +++ b/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h @@ -15,6 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "SpellAuraEffects.h" + #ifndef DEF_ULDUAR_H #define DEF_ULDUAR_H @@ -44,6 +46,7 @@ enum eTypes DATA_BRUNDIR, DATA_EXP_COMMANDER, + DATA_RAZORSCALE_CONTROL, // Kologarn: DATA_LEFT_ARM, @@ -55,6 +58,8 @@ enum eNPCs NPC_LEVIATHAN = 33113, NPC_IGNIS = 33118, NPC_RAZORSCALE = 33186, + NPC_RAZORSCALE_CONTROLLER = 33233, + NPC_STEELFORGED_DEFFENDER = 33236, NPC_EXPEDITION_COMMANDER = 33210, NPC_XT002 = 33293, NPC_STEELBREAKER = 32867, @@ -92,6 +97,12 @@ enum eGameObjects GO_LEVIATHAN_DOOR = 194905, GO_LEVIATHAN_GATE = 194630, 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, }; enum eTowerEvents @@ -107,4 +118,5 @@ enum eAchievementCriteria ACHIEVEMENT_CRITERIA_HOT_POCKET_10 = 10430, //ignis ACHIEVEMENT_CRITERIA_HOT_POCKET_25 = 10431, }; + #endif |