fix(Core/Scripts): Blackwing Lair overhaul (#3673)

* [Core/Scripts] BWL - Make Razorgore talk, script blackwing mage, make his spell break eggs

* more to vaelastrasz

* accidentally removed some of the waypoints, fuck me

* Broodlord Lashlayer overhaul + supressors

* Formations, waypoints for Ebonroc and roaming Flamegor (might be non-blizzlike)

* complete overhaul for the basic scripts, merge with TC

* last for today, door cleanup and nefarian refactor (from TC)

* Doors are now working, hooraay!

* Fix the boss gossip that we broke... non-intentionally lolz

* Vaelstraz intro - done

* small corrections to the timers, they are not blizzlike since we got no sniffs.. :^)

* nefarian checked, everything seems to be fine... let the cleanup begin now

* SQL seems fine as well, let's gooo

* Partially Revert "SQL seems fine as well, let's gooo"

This partially reverts commit b1750da58d169e9ed916eb6a6a95da93caeb0ff8.

* idk why mine's called wander_distance

* wtb new eyes

* lost an override @ flamegor

* more junk to fix the compile

* anything else? whining shit..

* SpellScript header..

* how about now?

* hopefully this does the trick, the condition in general works just fine, the spell is targeting the boss

* Update 0000_00_00_00.sql

fuck. you.

* Cleanup SQL, temp comment out code for creature relations so they don't pull several rooms at once

* Move the file with proper revision and location

* Remove the creature_relations *fix* until there's a proper core-side fix for it.

* spawndist > wander_distance

* compile fix

* lost a bracket in the merge

* *sigh*

* add new line at the end

* Nefarian's whitespaces

* Vael's whitespaces

* Razorgore good to go as well

* Header as well

* finale
This commit is contained in:
FALL1N1
2021-01-31 02:38:00 +02:00
committed by GitHub
parent cf1eddf266
commit 6ef7341313
11 changed files with 813 additions and 414 deletions

View File

@@ -7,23 +7,33 @@
#ifndef DEF_BLACKWING_LAIR_H
#define DEF_BLACKWING_LAIR_H
#include "CreatureAIImpl.h"
uint32 const EncounterCount = 8;
#define BRLScriptName "instance_blackwing_lair"
#define BWLScriptName "instance_blackwing_lair"
#define DataHeader "BWL"
enum BWLEncounter
{
BOSS_RAZORGORE = 0,
BOSS_VAELASTRAZ = 1,
BOSS_BROODLORD = 2,
BOSS_FIREMAW = 3,
BOSS_EBONROC = 4,
BOSS_FLAMEGOR = 5,
BOSS_CHROMAGGUS = 6,
BOSS_NEFARIAN = 7
// Encounter States/Boss GUIDs
DATA_RAZORGORE_THE_UNTAMED = 0,
DATA_VAELASTRAZ_THE_CORRUPT = 1,
DATA_BROODLORD_LASHLAYER = 2,
DATA_FIREMAW = 3,
DATA_EBONROC = 4,
DATA_FLAMEGOR = 5,
DATA_CHROMAGGUS = 6,
DATA_NEFARIAN = 7,
// Additional Data
DATA_LORD_VICTOR_NEFARIUS = 8,
// Doors
DATA_GO_CHROMAGGUS_DOOR = 9
};
enum CreatureIds
enum BWLCreatureIds
{
NPC_RAZORGORE = 12435,
NPC_BLACKWING_DRAGON = 12422,
@@ -32,7 +42,7 @@ enum CreatureIds
NPC_BLACKWING_WARLOCK = 12459,
NPC_VAELASTRAZ = 13020,
NPC_BROODLORD = 12017,
NPC_FIRENAW = 11983,
NPC_FIREMAW = 11983,
NPC_EBONROC = 14601,
NPC_FLAMEGOR = 11981,
NPC_CHROMAGGUS = 14020,
@@ -40,17 +50,17 @@ enum CreatureIds
NPC_NEFARIAN = 11583
};
enum BWLData64
enum BWLGameObjectIds
{
DATA_RAZORGORE_THE_UNTAMED = 1,
DATA_VAELASTRAZ_THE_CORRUPT,
DATA_BROODLORD_LASHLAYER,
DATA_FIRENAW,
DATA_EBONROC,
DATA_FLAMEGOR,
DATA_CHROMAGGUS,
DATA_LORD_VICTOR_NEFARIUS,
DATA_NEFARIAN
GO_BLACK_DRAGON_EGG = 177807,
GO_PORTCULLIS_RAZORGORE = 175946,
GO_PORTCULLIS_VAELASTRASZ = 175185,
GO_PORTCULLIS_BROODLORD = 179365,
GO_PORTCULLIS_THREEDRAGONS = 179115,
GO_CHROMAGGUS_LEVER = 179148,
GO_PORTCULLIS_CHROMAGGUS = 179116,
GO_PORTCULLIS_NEFARIAN = 179117,
GO_SUPPRESSION_DEVICE = 179784
};
enum BWLEvents
@@ -64,7 +74,10 @@ enum BWLMisc
{
// Razorgore Egg Event
ACTION_PHASE_TWO = 1,
DATA_EGG_EVENT
DATA_EGG_EVENT = 2,
TALK_EGG_BROKEN_RAND = 3,
SAY_NEFARIAN_VAEL_INTRO = 100003, // latest id in broadcast_text atm
};
#endif

View File

@@ -7,6 +7,9 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "blackwing_lair.h"
#include "GameObject.h"
#include "GameObjectAI.h"
#include "InstanceScript.h"
enum Say
{
@@ -19,7 +22,8 @@ enum Spells
SPELL_CLEAVE = 26350,
SPELL_BLASTWAVE = 23331,
SPELL_MORTALSTRIKE = 24573,
SPELL_KNOCKBACK = 25778
SPELL_KNOCKBACK = 25778,
SPELL_SUPPRESSION_AURA = 22247 // Suppression Device Spell
};
enum Events
@@ -28,7 +32,15 @@ enum Events
EVENT_BLASTWAVE = 2,
EVENT_MORTALSTRIKE = 3,
EVENT_KNOCKBACK = 4,
EVENT_CHECK = 5
EVENT_CHECK = 5,
// Suppression Device Events
EVENT_SUPPRESSION_CAST = 6,
EVENT_SUPPRESSION_RESET = 7
};
enum Actions
{
ACTION_DEACTIVATE = 0
};
class boss_broodlord : public CreatureScript
@@ -38,17 +50,11 @@ public:
struct boss_broodlordAI : public BossAI
{
boss_broodlordAI(Creature* creature) : BossAI(creature, BOSS_BROODLORD) { }
boss_broodlordAI(Creature* creature) : BossAI(creature, DATA_BROODLORD_LASHLAYER) { }
void EnterCombat(Unit* /*who*/) override
void EnterCombat(Unit* who) override
{
if (instance->GetBossState(BOSS_VAELASTRAZ) != DONE)
{
EnterEvadeMode();
return;
}
_EnterCombat();
BossAI::EnterCombat(who);
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_CLEAVE, 8000);
@@ -58,6 +64,16 @@ public:
events.ScheduleEvent(EVENT_CHECK, 1000);
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
std::list<GameObject*> _goList;
GetGameObjectListWithEntryInGrid(_goList, me, GO_SUPPRESSION_DEVICE, 200.0f);
for (std::list<GameObject*>::const_iterator itr = _goList.begin(); itr != _goList.end(); itr++)
((*itr)->AI()->DoAction(ACTION_DEACTIVATE));
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
@@ -75,17 +91,17 @@ public:
break;
case EVENT_BLASTWAVE:
DoCastVictim(SPELL_BLASTWAVE);
events.ScheduleEvent(EVENT_BLASTWAVE, urand(8000, 16000));
events.ScheduleEvent(EVENT_BLASTWAVE, 8000, 16000);
break;
case EVENT_MORTALSTRIKE:
DoCastVictim(SPELL_MORTALSTRIKE);
events.ScheduleEvent(EVENT_MORTALSTRIKE, urand(25000, 35000));
events.ScheduleEvent(EVENT_MORTALSTRIKE, 25000, 35000);
break;
case EVENT_KNOCKBACK:
DoCastVictim(SPELL_KNOCKBACK);
if (DoGetThreat(me->GetVictim()))
DoModifyThreatPercent(me->GetVictim(), -50);
events.ScheduleEvent(EVENT_KNOCKBACK, urand(15000, 30000));
events.ScheduleEvent(EVENT_KNOCKBACK, 15000, 30000);
break;
case EVENT_CHECK:
if (me->GetDistance(me->GetHomePosition()) > 150.0f)
@@ -108,7 +124,109 @@ public:
}
};
class go_suppression_device : public GameObjectScript
{
public:
go_suppression_device() : GameObjectScript("go_suppression_device") { }
struct go_suppression_deviceAI : public GameObjectAI
{
go_suppression_deviceAI(GameObject* go) : GameObjectAI(go), _instance(go->GetInstanceScript()), _active(true) { }
void InitializeAI() override
{
if (_instance->GetBossState(DATA_BROODLORD_LASHLAYER) == DONE)
{
Deactivate();
return;
}
_events.ScheduleEvent(EVENT_SUPPRESSION_CAST, 5000);
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SUPPRESSION_CAST:
if (go->GetGoState() == GO_STATE_READY)
{
go->CastSpell(nullptr, SPELL_SUPPRESSION_AURA);
go->SendCustomAnim(0);
}
_events.ScheduleEvent(EVENT_SUPPRESSION_CAST, 5000);
break;
case EVENT_SUPPRESSION_RESET:
Activate();
break;
}
}
}
void OnLootStateChanged(uint32 state, Unit* /*unit*/)
{
switch (state)
{
case GO_ACTIVATED:
Deactivate();
_events.CancelEvent(EVENT_SUPPRESSION_CAST);
_events.ScheduleEvent(EVENT_SUPPRESSION_RESET, 30000, 120000);
break;
case GO_JUST_DEACTIVATED: // This case prevents the Gameobject despawn by Disarm Trap
go->SetLootState(GO_READY);
break;
}
}
void DoAction(int32 action) override
{
if (action == ACTION_DEACTIVATE)
{
Deactivate();
_events.CancelEvent(EVENT_SUPPRESSION_RESET);
}
}
void Activate()
{
if (_active)
return;
_active = true;
if (go->GetGoState() == GO_STATE_ACTIVE)
go->SetGoState(GO_STATE_READY);
go->SetLootState(GO_READY);
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
_events.ScheduleEvent(EVENT_SUPPRESSION_CAST, 1000);
}
void Deactivate()
{
if (!_active)
return;
_active = false;
go->SetGoState(GO_STATE_ACTIVE);
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
_events.CancelEvent(EVENT_SUPPRESSION_CAST);
}
private:
InstanceScript* _instance;
EventMap _events;
bool _active;
};
GameObjectAI* GetAI(GameObject* go) const
{
return new go_suppression_deviceAI(go);
}
};
void AddSC_boss_broodlord()
{
new boss_broodlord();
new go_suppression_device();
}

View File

@@ -5,9 +5,13 @@
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "Player.h"
#include "blackwing_lair.h"
#include "InstanceScript.h"
#include "GameObject.h"
#include "GameObjectAI.h"
#include "Map.h"
#include "Player.h"
#include "ScriptedCreature.h"
enum Emotes
{
@@ -59,8 +63,13 @@ public:
struct boss_chromaggusAI : public BossAI
{
boss_chromaggusAI(Creature* creature) : BossAI(creature, BOSS_CHROMAGGUS)
boss_chromaggusAI(Creature* creature) : BossAI(creature, DATA_CHROMAGGUS)
{
Initialize();
Breath1_Spell = 0;
Breath2_Spell = 0;
// Select the 2 breaths that we are going to use until despawned
// 5 possiblities for the first breath, 4 for the second, 20 total possiblites
// This way we don't end up casting 2 of the same breath
@@ -85,7 +94,7 @@ public:
Breath2_Spell = SPELL_FROSTBURN;
break;
// B1 - TL
// B1 - TL
case 4:
Breath1_Spell = SPELL_TIMELAPSE;
Breath2_Spell = SPELL_INCINERATE;
@@ -103,7 +112,7 @@ public:
Breath2_Spell = SPELL_FROSTBURN;
break;
//B1 - Acid
//B1 - Acid
case 8:
Breath1_Spell = SPELL_CORROSIVEACID;
Breath2_Spell = SPELL_INCINERATE;
@@ -121,7 +130,7 @@ public:
Breath2_Spell = SPELL_FROSTBURN;
break;
//B1 - Ignite
//B1 - Ignite
case 12:
Breath1_Spell = SPELL_IGNITEFLESH;
Breath2_Spell = SPELL_INCINERATE;
@@ -139,7 +148,7 @@ public:
Breath2_Spell = SPELL_FROSTBURN;
break;
//B1 - Frost
//B1 - Frost
case 16:
Breath1_Spell = SPELL_FROSTBURN;
Breath2_Spell = SPELL_INCINERATE;
@@ -161,24 +170,24 @@ public:
EnterEvadeMode();
}
void Reset() override
void Initialize()
{
_Reset();
CurrentVurln_Spell = 0; // We use this to store our last vulnerabilty spell so we can remove it later
Enraged = false;
}
void EnterCombat(Unit* /*who*/) override
void Reset() override
{
if (instance->GetBossState(BOSS_FLAMEGOR) != DONE)
{
EnterEvadeMode();
return;
}
_EnterCombat();
_Reset();
events.ScheduleEvent(EVENT_SHIMMER, 0);
Initialize();
}
void EnterCombat(Unit* victim) override
{
BossAI::EnterCombat(victim);
events.ScheduleEvent(EVENT_SHIMMER, 1000);
events.ScheduleEvent(EVENT_BREATH_1, 30000);
events.ScheduleEvent(EVENT_BREATH_2, 60000);
events.ScheduleEvent(EVENT_AFFLICTION, 10000);
@@ -214,13 +223,13 @@ public:
break;
}
case EVENT_BREATH_1:
DoCastVictim(Breath1_Spell);
events.ScheduleEvent(EVENT_BREATH_1, 60000);
break;
DoCastVictim(Breath1_Spell);
events.ScheduleEvent(EVENT_BREATH_1, 60000);
break;
case EVENT_BREATH_2:
DoCastVictim(Breath2_Spell);
events.ScheduleEvent(EVENT_BREATH_2, 60000);
break;
DoCastVictim(Breath2_Spell);
events.ScheduleEvent(EVENT_BREATH_2, 60000);
break;
case EVENT_AFFLICTION:
{
Map::PlayerList const& players = me->GetMap()->GetPlayers();
@@ -230,14 +239,14 @@ public:
{
DoCast(player, RAND(SPELL_BROODAF_BLUE, SPELL_BROODAF_BLACK, SPELL_BROODAF_RED, SPELL_BROODAF_BRONZE, SPELL_BROODAF_GREEN), true);
if (player->HasAura(SPELL_BROODAF_BLUE) &&
if (player->HasAura(SPELL_BROODAF_BLUE) &&
player->HasAura(SPELL_BROODAF_BLACK) &&
player->HasAura(SPELL_BROODAF_RED) &&
player->HasAura(SPELL_BROODAF_BRONZE) &&
player->HasAura(SPELL_BROODAF_GREEN))
{
DoCast(player, SPELL_CHROMATIC_MUT_1);
}
{
DoCast(player, SPELL_CHROMATIC_MUT_1);
}
}
}
}
@@ -245,9 +254,12 @@ public:
break;
case EVENT_FRENZY:
DoCast(me, SPELL_FRENZY);
events.ScheduleEvent(EVENT_FRENZY, urand(10000, 15000));
events.ScheduleEvent(EVENT_FRENZY, 10000, 15000);
break;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
// Enrage if not already enraged and below 20%
@@ -273,7 +285,46 @@ public:
}
};
class go_chromaggus_lever : public GameObjectScript
{
public:
go_chromaggus_lever() : GameObjectScript("go_chromaggus_lever") { }
struct go_chromaggus_leverAI : public GameObjectAI
{
go_chromaggus_leverAI(GameObject* go) : GameObjectAI(go), _instance(go->GetInstanceScript()) { }
bool OnGossipHello(Player* player)
{
if (_instance->GetBossState(DATA_CHROMAGGUS) != DONE && _instance->GetBossState(DATA_CHROMAGGUS) != IN_PROGRESS)
{
_instance->SetBossState(DATA_CHROMAGGUS, IN_PROGRESS);
if (Creature* creature = _instance->instance->GetCreature(DATA_CHROMAGGUS))
creature->AI()->AttackStart(player);
if (GameObject* go = _instance->instance->GetGameObject(DATA_GO_CHROMAGGUS_DOOR))
_instance->HandleGameObject(0, true, go);
}
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE | GO_FLAG_IN_USE);
go->SetGoState(GO_STATE_ACTIVE);
return true;
}
private:
InstanceScript* _instance;
};
GameObjectAI* GetAI(GameObject* go) const override
{
return GetInstanceAI<go_chromaggus_leverAI>(go);
}
};
void AddSC_boss_chromaggus()
{
new boss_chromaggus();
new go_chromaggus_lever();
}

View File

@@ -29,20 +29,15 @@ public:
struct boss_ebonrocAI : public BossAI
{
boss_ebonrocAI(Creature* creature) : BossAI(creature, BOSS_EBONROC) { }
boss_ebonrocAI(Creature* creature) : BossAI(creature, DATA_EBONROC) { }
void EnterCombat(Unit* /*who*/) override
void EnterCombat(Unit* who) override
{
if (instance->GetBossState(BOSS_BROODLORD) != DONE)
{
EnterEvadeMode();
return;
}
_EnterCombat();
BossAI::EnterCombat(who);
events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000));
events.ScheduleEvent(EVENT_SHADOWFLAME, 10000, 20000);
events.ScheduleEvent(EVENT_WINGBUFFET, 30000);
events.ScheduleEvent(EVENT_SHADOWOFEBONROC, urand(8000, 10000));
events.ScheduleEvent(EVENT_SHADOWOFEBONROC, 8000, 10000);
}
void UpdateAI(uint32 diff) override
@@ -61,7 +56,7 @@ public:
{
case EVENT_SHADOWFLAME:
DoCastVictim(SPELL_SHADOWFLAME);
events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000));
events.ScheduleEvent(EVENT_SHADOWFLAME, 10000, 20000);
break;
case EVENT_WINGBUFFET:
DoCastVictim(SPELL_WINGBUFFET);
@@ -69,9 +64,12 @@ public:
break;
case EVENT_SHADOWOFEBONROC:
DoCastVictim(SPELL_SHADOWOFEBONROC);
events.ScheduleEvent(EVENT_SHADOWOFEBONROC, urand(8000, 10000));
events.ScheduleEvent(EVENT_SHADOWOFEBONROC, 8000, 10000);
break;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();

View File

@@ -29,18 +29,13 @@ public:
struct boss_firemawAI : public BossAI
{
boss_firemawAI(Creature* creature) : BossAI(creature, BOSS_FIREMAW) { }
boss_firemawAI(Creature* creature) : BossAI(creature, DATA_FIREMAW) { }
void EnterCombat(Unit* /*who*/) override
void EnterCombat(Unit* who) override
{
if (instance->GetBossState(BOSS_BROODLORD) != DONE)
{
EnterEvadeMode();
return;
}
_EnterCombat();
BossAI::EnterCombat(who);
events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000));
events.ScheduleEvent(EVENT_SHADOWFLAME, 10000, 20000);
events.ScheduleEvent(EVENT_WINGBUFFET, 30000);
events.ScheduleEvent(EVENT_FLAMEBUFFET, 5000);
}
@@ -61,7 +56,7 @@ public:
{
case EVENT_SHADOWFLAME:
DoCastVictim(SPELL_SHADOWFLAME);
events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000));
events.ScheduleEvent(EVENT_SHADOWFLAME, 10000, 20000);
break;
case EVENT_WINGBUFFET:
DoCastVictim(SPELL_WINGBUFFET);
@@ -74,6 +69,9 @@ public:
events.ScheduleEvent(EVENT_FLAMEBUFFET, 5000);
break;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();

View File

@@ -34,18 +34,13 @@ public:
struct boss_flamegorAI : public BossAI
{
boss_flamegorAI(Creature* creature) : BossAI(creature, BOSS_FLAMEGOR) { }
boss_flamegorAI(Creature* creature) : BossAI(creature, DATA_FLAMEGOR) { }
void EnterCombat(Unit* /*who*/) override
void EnterCombat(Unit* victim) override
{
if (instance->GetBossState(BOSS_BROODLORD) != DONE)
{
EnterEvadeMode();
return;
}
_EnterCombat();
BossAI::EnterCombat(victim);
events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000));
events.ScheduleEvent(EVENT_SHADOWFLAME, 10000, 20000);
events.ScheduleEvent(EVENT_WINGBUFFET, 30000);
events.ScheduleEvent(EVENT_FRENZY, 10000);
}
@@ -66,7 +61,7 @@ public:
{
case EVENT_SHADOWFLAME:
DoCastVictim(SPELL_SHADOWFLAME);
events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000));
events.ScheduleEvent(EVENT_SHADOWFLAME, 10000, 20000);
break;
case EVENT_WINGBUFFET:
DoCastVictim(SPELL_WINGBUFFET);
@@ -77,9 +72,12 @@ public:
case EVENT_FRENZY:
Talk(EMOTE_FRENZY);
DoCast(me, SPELL_FRENZY);
events.ScheduleEvent(EVENT_FRENZY, urand(8000, 10000));
events.ScheduleEvent(EVENT_FRENZY, 8000, 10000);
break;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();

View File

@@ -8,7 +8,11 @@
#include "ScriptedGossip.h"
#include "ScriptedCreature.h"
#include "blackwing_lair.h"
#include "GameObject.h"
#include "InstanceScript.h"
#include "MotionMaster.h"
#include "Player.h"
#include "TemporarySummon.h"
enum Events
{
@@ -154,28 +158,26 @@ public:
struct boss_victor_nefariusAI : public BossAI
{
boss_victor_nefariusAI(Creature* creature) : BossAI(creature, BOSS_NEFARIAN) { }
boss_victor_nefariusAI(Creature* creature) : BossAI(creature, DATA_NEFARIAN)
{
Initialize();
}
void Initialize()
{
SpawnedAdds = 0;
}
void Reset() override
{
SpawnedAdds = 0;
Initialize();
if (me->GetMapId() == 469)
{
// pussywizard:
bool reset = true;
if (instance)
if (/*Creature* nefarian = */instance->instance->GetCreature(instance->GetData64(DATA_NEFARIAN)))
reset = false;
if (reset)
if (!me->FindNearestCreature(NPC_NEFARIAN, 1000.0f, true))
_Reset();
// pussywizard:
if (!instance || instance->GetBossState(BOSS_NEFARIAN) == DONE || instance->GetBossState(BOSS_NEFARIAN) == IN_PROGRESS)
me->SetVisible(false);
else
me->SetVisible(true);
me->SetVisible(true);
me->SetPhaseMask(1, true);
me->SetUInt32Value(UNIT_NPC_FLAGS, 1);
me->setFaction(35);
@@ -201,14 +203,16 @@ public:
me->SetUInt32Value(UNIT_NPC_FLAGS, 0);
DoCast(me, SPELL_NEFARIANS_BARRIER);
me->SetStandState(UNIT_STAND_STATE_STAND);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
AttackStart(target);
events.ScheduleEvent(EVENT_SHADOW_BOLT, urand(3000, 10000));
events.ScheduleEvent(EVENT_FEAR, urand(10000, 20000));
//events.ScheduleEvent(EVENT_MIND_CONTROL, urand(30000, 35000));
events.ScheduleEvent(EVENT_MIND_CONTROL, urand(30000, 35000));
events.ScheduleEvent(EVENT_SPAWN_ADD, 10000);
}
void SummonedCreatureDies(Creature* summon, Unit*) override
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
{
if (summon->GetEntry() != NPC_NEFARIAN)
{
@@ -262,7 +266,7 @@ public:
case EVENT_SUCCESS_1:
if (Unit* player = me->SelectNearestPlayer(60.0f))
{
me->SetInFront(player);
me->SetFacingToObject(player);
Talk(SAY_SUCCESS);
if (GameObject* portcullis1 = me->FindNearestGameObject(GO_PORTCULLIS_ACTIVE, 65.0f))
portcullis1->SetGoState(GO_STATE_ACTIVE);
@@ -322,7 +326,7 @@ public:
events.ScheduleEvent(EVENT_MIND_CONTROL, urand(30000, 35000));
break;
case EVENT_SPAWN_ADD:
for (uint8 i = 0; i < 2; ++i)
for (uint8 i=0; i<2; ++i)
{
uint32 CreatureID;
if (urand(0, 2) == 0)
@@ -339,26 +343,25 @@ public:
{
if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianLoc[0]))
{
nefarian->AddUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD);
nefarian->SetCanFly(true);
nefarian->SetHover(false);
nefarian->setActive(true);
nefarian->SetHomePosition(NefarianLoc[1]);
nefarian->GetMotionMaster()->MoveCharge(NefarianLoc[1].GetPositionX(), NefarianLoc[1].GetPositionY(), NefarianLoc[1].GetPositionZ(), 15.0f);
nefarian->AI()->DoCastAOE(SPELL_SHADOWFLAME_INITIAL);
nefarian->SetCanFly(true);
nefarian->SetDisableGravity(true);
nefarian->CastSpell(nullptr, SPELL_SHADOWFLAME_INITIAL);
nefarian->GetMotionMaster()->MovePoint(1, NefarianLoc[1]);
}
events.CancelEvent(EVENT_MIND_CONTROL);
events.CancelEvent(EVENT_FEAR);
events.CancelEvent(EVENT_SHADOW_BOLT);
me->SetVisible(false);
EnterEvadeMode();
return;
}
}
events.ScheduleEvent(EVENT_SPAWN_ADD, 4000);
break;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
}
}
@@ -369,17 +372,17 @@ public:
{
// pussywizard:
InstanceScript* instance = player->GetInstanceScript();
if (!instance || instance->GetBossState(BOSS_NEFARIAN) == DONE)
if (!instance || instance->GetBossState(DATA_NEFARIAN) == DONE)
return;
CloseGossipMenuFor(player);
player->CLOSE_GOSSIP_MENU();
Talk(SAY_GAMESBEGIN_1);
BeginEvent(player);
}
}
private:
uint32 SpawnedAdds;
private:
uint32 SpawnedAdds;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -395,15 +398,23 @@ public:
struct boss_nefarianAI : public BossAI
{
boss_nefarianAI(Creature* creature) : BossAI(creature, BOSS_NEFARIAN) { }
boss_nefarianAI(Creature* creature) : BossAI(creature, DATA_NEFARIAN)
{
Initialize();
}
void Reset() override
void Initialize()
{
Phase3 = false;
canDespawn = false;
DespawnTimer = 30000;
}
void Reset() override
{
Initialize();
}
void JustReachedHome() override
{
canDespawn = true;
@@ -420,7 +431,7 @@ public:
Talk(SAY_RANDOM);
}
void JustDied(Unit* /*Killer*/) override
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
@@ -428,37 +439,40 @@ public:
void KilledUnit(Unit* victim) override
{
if (rand() % 5)
if (rand32() % 5)
return;
Talk(SAY_SLAY, victim);
}
void MovementInform(uint32 type, uint32 /*id*/) override
void MovementInform(uint32 type, uint32 id) override
{
if (type != POINT_MOTION_TYPE)
return;
me->SetCanFly(false);
me->SetDisableGravity(false);
me->SetWalk(false);
me->SetInCombatWithZone();
if (me->GetVictim())
AttackStart(me->GetVictim());
if (id == 1)
{
DoZoneInCombat();
if (me->GetVictim())
AttackStart(me->GetVictim());
}
}
void UpdateAI(uint32 diff) override
{
if (canDespawn && DespawnTimer <= diff)
{
instance->SetBossState(BOSS_NEFARIAN, FAIL);
instance->SetBossState(DATA_NEFARIAN, FAIL);
std::list<Creature*> constructList;
me->GetCreatureListWithEntryInGrid(constructList, NPC_BONE_CONSTRUCT, 500.0f);
for (std::list<Creature*>::const_iterator itr = constructList.begin(); itr != constructList.end(); ++itr)
(*itr)->DespawnOrUnsummon();
}
else DespawnTimer -= diff;
else
{
DespawnTimer -= diff;
}
if (!UpdateVictim())
return;
@@ -499,53 +513,56 @@ public:
case EVENT_CLASSCALL:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
switch (target->getClass())
{
case CLASS_MAGE:
Talk(SAY_MAGE);
DoCast(me, SPELL_MAGE);
break;
case CLASS_WARRIOR:
Talk(SAY_WARRIOR);
DoCast(me, SPELL_WARRIOR);
break;
case CLASS_DRUID:
Talk(SAY_DRUID);
DoCast(target, SPELL_DRUID);
break;
case CLASS_PRIEST:
Talk(SAY_PRIEST);
DoCast(me, SPELL_PRIEST);
break;
case CLASS_PALADIN:
Talk(SAY_PALADIN);
DoCast(me, SPELL_PALADIN);
break;
case CLASS_SHAMAN:
Talk(SAY_SHAMAN);
DoCast(me, SPELL_SHAMAN);
break;
case CLASS_WARLOCK:
Talk(SAY_WARLOCK);
DoCast(me, SPELL_WARLOCK);
break;
case CLASS_HUNTER:
Talk(SAY_HUNTER);
DoCast(me, SPELL_HUNTER);
break;
case CLASS_ROGUE:
Talk(SAY_ROGUE);
DoCast(me, SPELL_ROGUE);
break;
case CLASS_DEATH_KNIGHT:
Talk(SAY_DEATH_KNIGHT);
DoCast(me, SPELL_DEATH_KNIGHT);
break;
default:
break;
}
{
case CLASS_MAGE:
Talk(SAY_MAGE);
DoCast(me, SPELL_MAGE);
break;
case CLASS_WARRIOR:
Talk(SAY_WARRIOR);
DoCast(me, SPELL_WARRIOR);
break;
case CLASS_DRUID:
Talk(SAY_DRUID);
DoCast(target, SPELL_DRUID);
break;
case CLASS_PRIEST:
Talk(SAY_PRIEST);
DoCast(me, SPELL_PRIEST);
break;
case CLASS_PALADIN:
Talk(SAY_PALADIN);
DoCast(me, SPELL_PALADIN);
break;
case CLASS_SHAMAN:
Talk(SAY_SHAMAN);
DoCast(me, SPELL_SHAMAN);
break;
case CLASS_WARLOCK:
Talk(SAY_WARLOCK);
DoCast(me, SPELL_WARLOCK);
break;
case CLASS_HUNTER:
Talk(SAY_HUNTER);
DoCast(me, SPELL_HUNTER);
break;
case CLASS_ROGUE:
Talk(SAY_ROGUE);
DoCast(me, SPELL_ROGUE);
break;
case CLASS_DEATH_KNIGHT:
Talk(SAY_DEATH_KNIGHT);
DoCast(me, SPELL_DEATH_KNIGHT);
break;
default:
break;
}
events.ScheduleEvent(EVENT_CLASSCALL, urand(30000, 35000));
break;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
// Phase3 begins when health below 20 pct
@@ -557,7 +574,7 @@ public:
if ((*itr) && !(*itr)->IsAlive())
{
(*itr)->Respawn();
(*itr)->SetInCombatWithZone();
DoZoneInCombat((*itr));
(*itr)->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
(*itr)->SetReactState(REACT_AGGRESSIVE);
(*itr)->SetStandState(UNIT_STAND_STATE_STAND);

View File

@@ -24,7 +24,7 @@ enum Spells
SPELL_CHANNEL = 45537,
SPELL_EGG_DESTROY = 19873,
SPELL_CLEAVE = 22540,
SPELL_CLEAVE = 19632,
SPELL_WARSTOMP = 24375,
SPELL_FIREBALLVOLLEY = 22425,
SPELL_CONFLAGRATION = 23023
@@ -56,7 +56,7 @@ public:
struct boss_razorgoreAI : public BossAI
{
boss_razorgoreAI(Creature* creature) : BossAI(creature, BOSS_RAZORGORE) { }
boss_razorgoreAI(Creature* creature) : BossAI(creature, DATA_RAZORGORE_THE_UNTAMED) { }
void Reset() override
{
@@ -90,6 +90,9 @@ public:
{
if (action == ACTION_PHASE_TWO)
DoChangePhase();
if (action == TALK_EGG_BROKEN_RAND)
Talk(urand(SAY_EGGS_BROKEN1, SAY_EGGS_BROKEN3));
}
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
@@ -176,7 +179,18 @@ public:
void HandleOnHit()
{
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
{
instance->SetData(DATA_EGG_EVENT, SPECIAL);
}
if (GameObject* egg = GetCaster()->FindNearestGameObject(GO_EGG, 100))
{
if (!egg)
return;
GetCaster()->GetAI()->DoAction(TALK_EGG_BROKEN_RAND);
egg->SetLootState(GO_READY);
egg->UseDoorOrButton(10000);
}
}
void Register() override

View File

@@ -5,33 +5,41 @@
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "blackwing_lair.h"
#include "ScriptedGossip.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
constexpr float aNefariusSpawnLoc[4] = { -7466.16f, -1040.80f, 412.053f, 2.14675f };
enum Says
{
SAY_LINE1 = 0,
SAY_LINE2 = 1,
SAY_LINE3 = 2,
SAY_HALFLIFE = 3,
SAY_KILLTARGET = 4
SAY_LINE1 = 0,
SAY_LINE2 = 1,
SAY_LINE3 = 2,
SAY_HALFLIFE = 3,
SAY_KILLTARGET = 4
};
enum Gossip
{
GOSSIP_ID = 21334,
GOSSIP_ID = 21334,
};
enum Spells
{
SPELL_ESSENCEOFTHERED = 23513,
SPELL_FLAMEBREATH = 23461,
SPELL_FIRENOVA = 23462,
SPELL_TAILSWIPE = 15847,
SPELL_BURNINGADRENALINE = 23620,
SPELL_CLEAVE = 20684 //Chain cleave is most likely named something different and contains a dummy effect
SPELL_ESSENCEOFTHERED = 23513,
SPELL_FLAMEBREATH = 23461,
SPELL_FIRENOVA = 23462,
SPELL_TAILSWIPE = 15847,
SPELL_BURNINGADRENALINE = 18173, //Cast this one. It's what 3.3.5 DBM expects.
SPELL_BURNINGADRENALINE_EXPLOSION = 23478,
SPELL_CLEAVE = 19983, //Chain cleave is most likely named something different and contains a dummy effect
SPELL_NEFARIUS_CORRUPTION = 23642,
SPELL_RED_LIGHTNING = 19484,
};
enum Events
@@ -40,13 +48,16 @@ enum Events
EVENT_SPEECH_2 = 2,
EVENT_SPEECH_3 = 3,
EVENT_SPEECH_4 = 4,
EVENT_ESSENCEOFTHERED = 5,
EVENT_FLAMEBREATH = 6,
EVENT_FIRENOVA = 7,
EVENT_TAILSWIPE = 8,
EVENT_CLEAVE = 9,
EVENT_BURNINGADRENALINE_CASTER = 10,
EVENT_BURNINGADRENALINE_TANK = 11
EVENT_SPEECH_5 = 5,
EVENT_SPEECH_6 = 6,
EVENT_SPEECH_7 = 7,
EVENT_ESSENCEOFTHERED = 8,
EVENT_FLAMEBREATH = 9,
EVENT_FIRENOVA = 10,
EVENT_TAILSWIPE = 11,
EVENT_CLEAVE = 12,
EVENT_BURNINGADRENALINE_CASTER = 13,
EVENT_BURNINGADRENALINE_TANK = 14,
};
class boss_vaelastrasz : public CreatureScript
@@ -56,11 +67,19 @@ public:
struct boss_vaelAI : public BossAI
{
boss_vaelAI(Creature* creature) : BossAI(creature, BOSS_VAELASTRAZ)
boss_vaelAI(Creature* creature) : BossAI(creature, DATA_VAELASTRAZ_THE_CORRUPT)
{
creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
creature->setFaction(35);
creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
Initialize();
}
void Initialize()
{
PlayerGUID = 0;
HasYelled = false;
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
me->setFaction(35);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
void Reset() override
@@ -68,14 +87,13 @@ public:
_Reset();
me->SetStandState(UNIT_STAND_STATE_DEAD);
PlayerGUID = 0;
HasYelled = false;
me->SetReactState(REACT_PASSIVE);
Initialize();
}
void EnterCombat(Unit* /*who*/) override
void EnterCombat(Unit* victim) override
{
_EnterCombat();
BossAI::EnterCombat(victim);
DoCast(me, SPELL_ESSENCEOFTHERED);
me->SetHealth(me->CountPctFromMaxHealth(30));
@@ -99,7 +117,7 @@ public:
void KilledUnit(Unit* victim) override
{
if (rand() % 5)
if (rand32() % 5)
return;
Talk(SAY_KILLTARGET, victim);
@@ -117,22 +135,42 @@ public:
switch (eventId)
{
case EVENT_SPEECH_1:
me->SummonCreature(NPC_VICTOR_NEFARIUS, aNefariusSpawnLoc[0], aNefariusSpawnLoc[1], aNefariusSpawnLoc[2], aNefariusSpawnLoc[3], TEMPSUMMON_TIMED_DESPAWN, 26000);
events.ScheduleEvent(EVENT_SPEECH_2, 1000);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
break;
case EVENT_SPEECH_2:
if (Creature* nefarius = me->GetMap()->GetCreature(m_nefariusGuid))
{
nefarius->CastSpell(me, SPELL_NEFARIUS_CORRUPTION, TRIGGERED_CAST_DIRECTLY);
nefarius->MonsterYell(SAY_NEFARIAN_VAEL_INTRO, LANG_UNIVERSAL, 0);
nefarius->SetStandState(UNIT_STAND_STATE_STAND);
}
events.ScheduleEvent(EVENT_SPEECH_3, 18000);
break;
case EVENT_SPEECH_3:
if (Creature* nefarius = me->GetMap()->GetCreature(m_nefariusGuid))
nefarius->CastSpell(me, SPELL_RED_LIGHTNING, TRIGGERED_NONE);
events.ScheduleEvent(EVENT_SPEECH_4, 2000);
break;
case EVENT_SPEECH_4:
Talk(SAY_LINE1);
me->SetStandState(UNIT_STAND_STATE_STAND);
me->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
events.ScheduleEvent(EVENT_SPEECH_2, 12000);
events.ScheduleEvent(EVENT_SPEECH_5, 12000);
break;
case EVENT_SPEECH_2:
case EVENT_SPEECH_5:
Talk(SAY_LINE2);
me->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
events.ScheduleEvent(EVENT_SPEECH_3, 12000);
events.ScheduleEvent(EVENT_SPEECH_6, 12000);
break;
case EVENT_SPEECH_3:
case EVENT_SPEECH_6:
Talk(SAY_LINE3);
me->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
events.ScheduleEvent(EVENT_SPEECH_4, 16000);
events.ScheduleEvent(EVENT_SPEECH_7, 17000);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
break;
case EVENT_SPEECH_4:
case EVENT_SPEECH_7:
me->setFaction(103);
if (PlayerGUID && ObjectAccessor::GetUnit(*me, PlayerGUID))
AttackStart(ObjectAccessor::GetUnit(*me, PlayerGUID));;
@@ -155,7 +193,7 @@ public:
break;
case EVENT_FLAMEBREATH:
DoCastVictim(SPELL_FLAMEBREATH);
events.ScheduleEvent(EVENT_FLAMEBREATH, urand(8000, 14000));
events.ScheduleEvent(EVENT_FLAMEBREATH, 8000, 14000);
break;
case EVENT_FIRENOVA:
DoCastVictim(SPELL_FIRENOVA);
@@ -171,27 +209,25 @@ public:
break;
case EVENT_BURNINGADRENALINE_CASTER:
{
Unit* target = nullptr;
uint8 i = 0;
while (i < 3) // max 3 tries to get a random target with power_mana
//selects a random target that isn't the current victim and is a mana user (selects mana users) but not pets
//it also ignores targets who have the aura. We don't want to place the debuff on the same target twice.
if (Unit *target = SelectTarget(SELECT_TARGET_RANDOM, 1, [&](Unit* u) { return u && !u->IsPet() && u->getPowerType() == POWER_MANA && !u->HasAura(SPELL_BURNINGADRENALINE); }))
{
++i;
target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); // not aggro leader
if (target && target->getPowerType() == POWER_MANA)
i = 3;
me->CastSpell(target, SPELL_BURNINGADRENALINE, true);
}
if (target) // cast on self (see below)
target->CastSpell(target, SPELL_BURNINGADRENALINE, true);
}
//reschedule the event
events.ScheduleEvent(EVENT_BURNINGADRENALINE_CASTER, 15000);
break;
case EVENT_BURNINGADRENALINE_TANK:
// have the victim cast the spell on himself otherwise the third effect aura will be applied to Vael instead of the player
me->GetVictim()->CastSpell(me->GetVictim(), SPELL_BURNINGADRENALINE, true);
//Vael has to cast it himself; contrary to the previous commit's comment. Nothing happens otherwise.
me->CastSpell(me->GetVictim(), SPELL_BURNINGADRENALINE, true);
events.ScheduleEvent(EVENT_BURNINGADRENALINE_TANK, 45000);
break;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
// Yell if hp lower than 15%
@@ -204,27 +240,70 @@ public:
DoMeleeAttackIfReady();
}
void JustSummoned(Creature* summoned) override
{
if (summoned->GetEntry() == NPC_VICTOR_NEFARIUS)
{
// Set not selectable, so players won't interact with it
summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
m_nefariusGuid = summoned->GetGUID();
}
}
void sGossipSelect(Player* player, uint32 sender, uint32 action) override
{
if (sender == GOSSIP_ID && action == 0)
{
CloseGossipMenuFor(player);
player->CLOSE_GOSSIP_MENU();
BeginSpeech(player);
}
}
private:
uint64 PlayerGUID;
bool HasYelled;
private:
uint64 PlayerGUID;
uint64 m_nefariusGuid;
bool HasYelled;
};
CreatureAI* GetAI(Creature* creature) const override
{
return new boss_vaelAI(creature);
return GetInstanceAI<boss_vaelAI>(creature);
}
};
// Need to define an aurascript for EVENT_BURNINGADRENALINE's death effect.
// 18173 - Burning Adrenaline
class spell_vael_burning_adrenaline : public SpellScriptLoader
{
public:
spell_vael_burning_adrenaline() : SpellScriptLoader("spell_vael_burning_adrenaline") { }
class spell_vael_burning_adrenaline_AuraScript : public AuraScript
{
PrepareAuraScript(spell_vael_burning_adrenaline_AuraScript);
void OnAuraRemoveHandler(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
//The tooltip says the on death the AoE occurs. According to information: http://qaliaresponse.stage.lithium.com/t5/WoW-Mayhem/Surviving-Burning-Adrenaline-For-tanks/td-p/48609
//Burning Adrenaline can be survived therefore Blizzard's implementation was an AoE bomb that went off if you were still alive and dealt
//damage to the target. You don't have to die for it to go off. It can go off whether you live or die.
GetTarget()->CastSpell(GetTarget(), SPELL_BURNINGADRENALINE_EXPLOSION, true);
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_vael_burning_adrenaline_AuraScript::OnAuraRemoveHandler, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_vael_burning_adrenaline_AuraScript();
}
};
void AddSC_boss_vaelastrasz()
{
new boss_vaelastrasz();
new spell_vael_burning_adrenaline();
}

View File

@@ -5,22 +5,29 @@
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "PassiveAI.h"
#include "blackwing_lair.h"
#include "GameObject.h"
#include "InstanceScript.h"
#include "Map.h"
#include "MotionMaster.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "TemporarySummon.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
/*
Blackwing Lair Encounter:
1 - boss_razorgore.cpp
2 - boss_vaelastrasz.cpp
3 - boss_broodlord_lashlayer.cpp
4 - boss_firemaw.cpp
5 - boss_ebonroc.cpp
6 - boss_flamegor.cpp
7 - boss_chromaggus.cpp
8 - boss_nefarian.cpp
*/
DoorData const doorData[] =
{
{ GO_PORTCULLIS_RAZORGORE, DATA_RAZORGORE_THE_UNTAMED, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, // ID 175946 || GUID 7230
{ GO_PORTCULLIS_VAELASTRASZ, DATA_VAELASTRAZ_THE_CORRUPT, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, // ID 175185 || GUID 7229
{ GO_PORTCULLIS_BROODLORD, DATA_BROODLORD_LASHLAYER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, // ID 179365 || GUID 75159
{ GO_PORTCULLIS_THREEDRAGONS, DATA_FIREMAW, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, // ID 179115 || GUID 75165
{ GO_PORTCULLIS_THREEDRAGONS, DATA_EBONROC, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, // ID 179115 || GUID 75165
{ GO_PORTCULLIS_THREEDRAGONS, DATA_FLAMEGOR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, // ID 179115 || GUID 75165
{ GO_PORTCULLIS_CHROMAGGUS, DATA_CHROMAGGUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, // ID 179116 || GUID 75161
{ GO_PORTCULLIS_NEFARIAN, DATA_NEFARIAN, DOOR_TYPE_ROOM, BOUNDARY_NONE}, // ID 179117 || GUID 75164
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE} // END
};
Position const SummonPosition[8] =
{
@@ -39,13 +46,16 @@ uint32 const Entry[5] = {12422, 12458, 12416, 12420, 12459};
class instance_blackwing_lair : public InstanceMapScript
{
public:
instance_blackwing_lair() : InstanceMapScript(BRLScriptName, 469) { }
instance_blackwing_lair() : InstanceMapScript(BWLScriptName, 469) { }
struct instance_blackwing_lair_InstanceMapScript : public InstanceScript
{
instance_blackwing_lair_InstanceMapScript(Map* map) : InstanceScript(map)
{
//SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadDoorData(doorData);
//LoadObjectData(creatureData, gameObjectData);
}
void Initialize() override
@@ -53,121 +63,110 @@ public:
// Razorgore
EggCount = 0;
EggEvent = 0;
RazorgoreTheUntamedGUID = 0;
RazorgoreDoorGUID = 0;
EggList.clear();
// Vaelastrasz the Corrupt
VaelastraszTheCorruptGUID = 0;
VaelastraszDoorGUID = 0;
// Broodlord Lashlayer
BroodlordLashlayerGUID = 0;
BroodlordDoorGUID = 0;
// 3 Dragons
FiremawGUID = 0;
EbonrocGUID = 0;
FlamegorGUID = 0;
ChrommagusDoorGUID = 0;
// Chormaggus
ChromaggusGUID = 0;
NefarianDoorGUID = 0;
// Nefarian
LordVictorNefariusGUID = 0;
NefarianGUID = 0;
}
void OnCreatureCreate(Creature* creature) override
{
InstanceScript::OnCreatureCreate(creature);
switch (creature->GetEntry())
{
case NPC_RAZORGORE:
RazorgoreTheUntamedGUID = creature->GetGUID();
break;
case NPC_BLACKWING_DRAGON:
case NPC_BLACKWING_TASKMASTER:
case NPC_BLACKWING_LEGIONAIRE:
case NPC_BLACKWING_WARLOCK:
if (Creature* razor = instance->GetCreature(RazorgoreTheUntamedGUID))
razor->AI()->JustSummoned(creature);
if (Creature* razor = instance->GetCreature(DATA_RAZORGORE_THE_UNTAMED))
if (CreatureAI* razorAI = razor->AI())
razorAI->JustSummoned(creature);
break;
case NPC_VAELASTRAZ:
VaelastraszTheCorruptGUID = creature->GetGUID();
break;
case NPC_BROODLORD:
BroodlordLashlayerGUID = creature->GetGUID();
break;
case NPC_FIRENAW:
FiremawGUID = creature->GetGUID();
break;
case NPC_EBONROC:
EbonrocGUID = creature->GetGUID();
break;
case NPC_FLAMEGOR:
FlamegorGUID = creature->GetGUID();
break;
case NPC_CHROMAGGUS:
ChromaggusGUID = creature->GetGUID();
break;
case NPC_VICTOR_NEFARIUS:
LordVictorNefariusGUID = creature->GetGUID();
break;
case NPC_NEFARIAN:
NefarianGUID = creature->GetGUID();
default:
break;
}
}
void OnGameObjectCreate(GameObject* go) override
{
switch (go->GetEntry())
InstanceScript::OnGameObjectCreate(go);
switch(go->GetEntry())
{
case 177807: // Egg
if (GetBossState(BOSS_FIREMAW) == DONE)
case GO_BLACK_DRAGON_EGG:
if (GetBossState(DATA_FIREMAW) == DONE)
go->SetPhaseMask(2, true);
else
EggList.push_back(go->GetGUID());
break;
case 175946: // Door
RazorgoreDoorGUID = go->GetGUID();
HandleGameObject(0, GetBossState(BOSS_RAZORGORE) == DONE, go);
case GO_PORTCULLIS_RAZORGORE:
case GO_PORTCULLIS_VAELASTRASZ:
case GO_PORTCULLIS_BROODLORD:
case GO_PORTCULLIS_THREEDRAGONS:
case GO_PORTCULLIS_CHROMAGGUS:
case GO_PORTCULLIS_NEFARIAN:
AddDoor(go, true);
break;
case 175185: // Door
VaelastraszDoorGUID = go->GetGUID();
HandleGameObject(0, GetBossState(BOSS_VAELASTRAZ) == DONE, go);
break;
case 180424: // Door
BroodlordDoorGUID = go->GetGUID();
HandleGameObject(0, GetBossState(BOSS_BROODLORD) == DONE, go);
break;
case 185483: // Door
ChrommagusDoorGUID = go->GetGUID();
HandleGameObject(0, GetBossState(BOSS_FIREMAW) == DONE && GetBossState(BOSS_EBONROC) == DONE && GetBossState(BOSS_FLAMEGOR) == DONE, go);
break;
case 181125: // Door
NefarianDoorGUID = go->GetGUID();
HandleGameObject(0, GetBossState(BOSS_CHROMAGGUS) == DONE, go);
default:
break;
}
}
void OnGameObjectRemove(GameObject* go) override
{
if (go->GetEntry() == 177807) // Egg
InstanceScript::OnGameObjectRemove(go);
if (go->GetEntry() == GO_BLACK_DRAGON_EGG)
EggList.remove(go->GetGUID());
switch (go->GetEntry())
{
case GO_PORTCULLIS_RAZORGORE:
case GO_PORTCULLIS_VAELASTRASZ:
case GO_PORTCULLIS_BROODLORD:
case GO_PORTCULLIS_THREEDRAGONS:
case GO_PORTCULLIS_CHROMAGGUS:
case GO_PORTCULLIS_NEFARIAN:
AddDoor(go, false);
break;
default:
break;
}
}
bool CheckRequiredBosses(uint32 bossId, Player const* /* player */) const override
{
switch (bossId)
{
case DATA_BROODLORD_LASHLAYER:
if (GetBossState(DATA_VAELASTRAZ_THE_CORRUPT) != DONE)
return false;
break;
case DATA_FIREMAW:
case DATA_EBONROC:
case DATA_FLAMEGOR:
if (GetBossState(DATA_BROODLORD_LASHLAYER) != DONE)
return false;
break;
case DATA_CHROMAGGUS:
if (GetBossState(DATA_FIREMAW) != DONE
|| GetBossState(DATA_EBONROC) != DONE
|| GetBossState(DATA_FLAMEGOR) != DONE)
return false;
break;
default:
break;
}
return true;
}
bool SetBossState(uint32 type, EncounterState state) override
{
// pussywizard:
if (GetBossState(type) == DONE && state != DONE) // prevent undoneing a boss xd
return false;
if (!InstanceScript::SetBossState(type, state))
return false;
switch (type)
{
case BOSS_RAZORGORE:
HandleGameObject(RazorgoreDoorGUID, state == DONE);
case DATA_RAZORGORE_THE_UNTAMED:
if (state == DONE)
{
for (std::list<uint64>::const_iterator itr = EggList.begin(); itr != EggList.end(); ++itr)
@@ -176,30 +175,16 @@ public:
}
SetData(DATA_EGG_EVENT, NOT_STARTED);
break;
case BOSS_VAELASTRAZ:
HandleGameObject(VaelastraszDoorGUID, state == DONE);
break;
case BOSS_BROODLORD:
HandleGameObject(BroodlordDoorGUID, state == DONE);
break;
case BOSS_FIREMAW:
case BOSS_EBONROC:
case BOSS_FLAMEGOR:
HandleGameObject(ChrommagusDoorGUID, GetBossState(BOSS_FIREMAW) == DONE && GetBossState(BOSS_EBONROC) == DONE && GetBossState(BOSS_FLAMEGOR) == DONE);
break;
case BOSS_CHROMAGGUS:
HandleGameObject(NefarianDoorGUID, state == DONE);
break;
case BOSS_NEFARIAN:
case DATA_NEFARIAN:
switch (state)
{
case NOT_STARTED:
if (Creature* nefarian = instance->GetCreature(NefarianGUID))
if (Creature* nefarian = instance->GetCreature(DATA_NEFARIAN))
nefarian->DespawnOrUnsummon();
break;
case FAIL:
_events.ScheduleEvent(EVENT_RESPAWN_NEFARIUS, 15 * IN_MILLISECONDS * MINUTE);
SetBossState(BOSS_NEFARIAN, NOT_STARTED);
_events.ScheduleEvent(EVENT_RESPAWN_NEFARIUS, 15 * 60 * IN_MILLISECONDS); //15min
SetBossState(DATA_NEFARIAN, NOT_STARTED);
break;
default:
break;
@@ -209,33 +194,6 @@ public:
return true;
}
uint64 GetData64(uint32 id) const override
{
switch (id)
{
case DATA_RAZORGORE_THE_UNTAMED:
return RazorgoreTheUntamedGUID;
case DATA_VAELASTRAZ_THE_CORRUPT:
return VaelastraszTheCorruptGUID;
case DATA_BROODLORD_LASHLAYER:
return BroodlordLashlayerGUID;
case DATA_FIRENAW:
return FiremawGUID;
case DATA_EBONROC:
return EbonrocGUID;
case DATA_FLAMEGOR:
return FlamegorGUID;
case DATA_CHROMAGGUS:
return ChromaggusGUID;
case DATA_LORD_VICTOR_NEFARIUS:
return LordVictorNefariusGUID;
case DATA_NEFARIAN:
return NefarianGUID;
}
return 0;
}
void SetData(uint32 type, uint32 data) override
{
if (type == DATA_EGG_EVENT)
@@ -243,7 +201,7 @@ public:
switch (data)
{
case IN_PROGRESS:
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 45 * IN_MILLISECONDS);
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 45000);
EggEvent = data;
EggCount = 0;
break;
@@ -255,13 +213,13 @@ public:
case SPECIAL:
if (++EggCount == 15)
{
if (Creature* razor = instance->GetCreature(RazorgoreTheUntamedGUID))
if (Creature* razor = instance->GetCreature(DATA_RAZORGORE_THE_UNTAMED))
{
SetData(DATA_EGG_EVENT, DONE);
razor->RemoveAurasDueToSpell(42013); // MindControl
DoRemoveAurasDueToSpellOnPlayers(42013);
}
_events.ScheduleEvent(EVENT_RAZOR_PHASE_TWO, IN_MILLISECONDS);
_events.ScheduleEvent(EVENT_RAZOR_PHASE_TWO, 1000);
_events.CancelEvent(EVENT_RAZOR_SPAWN);
}
if (EggEvent == NOT_STARTED)
@@ -274,8 +232,8 @@ public:
void OnUnitDeath(Unit* unit) override
{
//! HACK, needed because of buggy CreatureAI after charm
if (unit->GetEntry() == NPC_RAZORGORE && GetBossState(BOSS_RAZORGORE) != DONE)
SetBossState(BOSS_RAZORGORE, DONE);
if (unit->GetEntry() == NPC_RAZORGORE && GetBossState(DATA_RAZORGORE_THE_UNTAMED) != DONE)
SetBossState(DATA_RAZORGORE_THE_UNTAMED, DONE);
}
void Update(uint32 diff) override
@@ -290,18 +248,18 @@ public:
switch (eventId)
{
case EVENT_RAZOR_SPAWN:
for (uint8 i = urand(2, 5); i > 0 ; --i)
if (Creature* summon = instance->SummonCreature(Entry[urand(0, 4)], SummonPosition[urand(0, 7)]))
summon->SetInCombatWithZone();
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, urand(12, 17)*IN_MILLISECONDS);
for (uint8 i = urand(2, 5); i > 0; --i)
if (Creature* summon = instance->SummonCreature(Entry[urand(0, 4)], SummonPosition[urand(0, 7)]))
summon->AI()->DoZoneInCombat();
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 12000, 17000);
break;
case EVENT_RAZOR_PHASE_TWO:
_events.CancelEvent(EVENT_RAZOR_SPAWN);
if (Creature* razor = instance->GetCreature(RazorgoreTheUntamedGUID))
if (Creature* razor = instance->GetCreature(DATA_RAZORGORE_THE_UNTAMED))
razor->AI()->DoAction(ACTION_PHASE_TWO);
break;
case EVENT_RESPAWN_NEFARIUS:
if (Creature* nefarius = instance->GetCreature(LordVictorNefariusGUID))
if (Creature* nefarius = instance->GetCreature(DATA_LORD_VICTOR_NEFARIUS))
{
nefarius->SetPhaseMask(1, true);
nefarius->setActive(true);
@@ -316,43 +274,51 @@ public:
protected:
// Misc
EventMap _events;
// Razorgore
uint8 EggCount;
uint32 EggEvent;
uint64 RazorgoreTheUntamedGUID;
uint64 RazorgoreDoorGUID;
std::list<uint64> EggList;
// Vaelastrasz the Corrupt
uint64 VaelastraszTheCorruptGUID;
uint64 VaelastraszDoorGUID;
// Broodlord Lashlayer
uint64 BroodlordLashlayerGUID;
uint64 BroodlordDoorGUID;
// 3 Dragons
uint64 FiremawGUID;
uint64 EbonrocGUID;
uint64 FlamegorGUID;
uint64 ChrommagusDoorGUID;
// Chormaggus
uint64 ChromaggusGUID;
uint64 NefarianDoorGUID;
// Nefarian
uint64 LordVictorNefariusGUID;
uint64 NefarianGUID;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
InstanceScript* GetInstanceScript(InstanceMap* map) const
{
return new instance_blackwing_lair_InstanceMapScript(map);
}
};
// 22539 - Shadowflame (used in Blackwing Lair)
class spell_bwl_shadowflame : public SpellScriptLoader
{
public:
spell_bwl_shadowflame() : SpellScriptLoader("spell_bwl_shadowflame") { }
class spell_bwl_shadowflame_SpellScript : public SpellScript
{
PrepareSpellScript(spell_bwl_shadowflame_SpellScript);
void HandleEffectScriptEffect(SpellEffIndex /*effIndex*/)
{
// If the victim of the spell does not have "Onyxia Scale Cloak" - add the Shadow Flame DoT (22682)
if (Unit* victim = GetHitUnit())
if(!victim->HasAura(22683))
victim->AddAura(22682, victim);
}
void Register()
{
OnEffectHitTarget += SpellEffectFn(spell_bwl_shadowflame_SpellScript::HandleEffectScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const
{
return new spell_bwl_shadowflame_SpellScript;
}
};
void AddSC_instance_blackwing_lair()
{
new instance_blackwing_lair();
new spell_bwl_shadowflame();
}