fix(Scripts/BRD): Magmus, Emperor, Priestess, Arena improvements (#8102)

This commit is contained in:
patou01
2021-12-16 12:14:29 +01:00
committed by GitHub
parent 886ea162e8
commit 9b3b61139a
14 changed files with 1203 additions and 332 deletions

View File

@@ -0,0 +1,43 @@
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1632675335691344600');
-- add yells emperor
DELETE FROM `creature_text` WHERE `CreatureID` = 9019;
INSERT INTO `creature_text` (`CreatureID`,`GroupID`,`ID`,`Text`,`Type`,`Language`,`Probability`,`Emote`,`Duration`,`Sound`,`BroadcastTextId`,`TextRange`,`COMMENT`) VALUES
(9019,0,0,'Come to aid the Throne!',14,0,100,0,0,0,0,0,'Aggro line council alive'),
(9019,1,0,'I will crush you into little tiny pieces!',14,0,100,0,0,0,5457,0,'Aggro line council dead'),
(9019,2,0,'Hail to the king, baby!',14,0,100,0,0,0,5431,0,'Killing player'),
(9019,3,0,'Your efforts are utterly pointless, fools! You will never be able to defeat me!',14,0,100,0,0,0,5312,0,'Killing council 1'),
(9019,4,0,'They were just getting in the way anyways.',14,0,100,0,0,0,5313,0,'Killing council 2'),
(9019,5,0,'Ha! You can''t even begin to imagine the futility of your efforts.',14,0,100,0,0,0,5314,0,'Killing council 3'),
(9019,6,0,'Is that the best you can do? Do you really expect that you could defeat someone as awe inspiring as me?',14,0,100,0,0,0,5315,0,'Killing council 4'),
(9019,7,0,'Thank you for clearing out those foolish senators. Now prepare to meet your doom at the hands of Ragnaros'' most powerful servant.',14,0,100,0,0,0,5311,0,'Killing all council');
-- priestess yell
UPDATE `creature_template` SET `ScriptName` = 'boss_high_priestess_thaurissan' WHERE (`entry` = 10076);
DELETE FROM `creature_text` where `CreatureID` = 10076;
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `BroadcastTextId`)
VALUES (10076, 0, 0, 'You will not harm Emperor Thaurissan!', 14, 0);
-- ironhand guardians, add cpp script, remove smartAI and smartscripts
UPDATE `creature_template` SET `AIName` = '', `ScriptName` = 'brd_ironhand_guardian' WHERE (`entry` = 8982);
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 8982) AND (`source_type` = 0) AND (`id` IN (0, 1));
-- flamekeepers
DELETE FROM `pool_template` WHERE `entry` = 1550;
INSERT INTO `pool_template` (`entry`, `max_limit`, `description`)
VALUES (1550, 2, 'BRD Lyceum shadowforge flame keepers');
DELETE FROM `pool_creature` WHERE `guid` IN (47302, 47303, 91119, 91120);
INSERT INTO `pool_creature` (`guid`, `pool_entry`, `chance`, `description`) VALUES
(47302, 1550, 0, 'BRD Lyceum shadowforge flame keepers'),
(47303, 1550, 0, 'BRD Lyceum shadowforge flame keepers'),
(91119, 1550, 0, 'BRD Lyceum shadowforge flame keepers'),
(91120, 1550, 0, 'BRD Lyceum shadowforge flame keepers');
-- moira and priestess are mages, not paladins.
UPDATE `creature_template` SET `unit_class` = 8 WHERE `entry` IN (8929, 10076);
-- scripts for bosses in arena
UPDATE `creature_template` SET `ScriptName` = 'boss_eviscerator' WHERE (`entry` = 9029);
UPDATE `creature_template` SET `ScriptName` = 'boss_okthor' WHERE (`entry` = 9030);
UPDATE `creature_template` SET `ScriptName` = 'boss_hedrum' WHERE (`entry` = 9032);

View File

@@ -23,16 +23,18 @@
#include "ScriptedGossip.h"
#include "WorldSession.h"
enum ShadowforgeBrazier
enum IronhandData
{
SAY_MAGMUS_BRAZIER_LIT = 0
IRONHAND_FLAMES_TIMER = 16000,
IRONHAND_FLAMES_TIMER_RAND = 3000,
IRONHAND_N_GROUPS = 3,
SPELL_GOUT_OF_FLAMES = 15529
};
//go_shadowforge_brazier
class go_shadowforge_brazier : public GameObjectScript
{
public:
go_shadowforge_brazier() : GameObjectScript("go_shadowforge_brazier") { }
go_shadowforge_brazier() : GameObjectScript("go_shadowforge_brazier") {}
bool OnGossipHello(Player* /*player*/, GameObject* go) override
{
@@ -46,68 +48,101 @@ public:
return false;
}
// Check if the opposite brazier is lit - if it is, open the gates.
if ((go->GetGUID() == northBrazier->GetGUID() && southBrazier->GetGoState() == GO_STATE_ACTIVE)
|| (go->GetGUID() == southBrazier->GetGUID() && northBrazier->GetGoState() == GO_STATE_ACTIVE))
// should only happen on first brazier
if (instance->GetData(TYPE_LYCEUM) == NOT_STARTED)
{
if (instance->GetData(TYPE_LYCEUM) == IN_PROGRESS)
{
instance->SetData(TYPE_LYCEUM, DONE);
}
else
{
instance->SetData(TYPE_LYCEUM, IN_PROGRESS);
}
if (Creature* magmus = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_MAGMUS)))
{
if (magmus->IsAlive())
{
magmus->AI()->Talk(SAY_MAGMUS_BRAZIER_LIT);
}
}
instance->HandleGameObject(instance->GetGuidData(DATA_GOLEM_DOOR_N), true);
instance->HandleGameObject(instance->GetGuidData(DATA_GOLEM_DOOR_S), true);
instance->SetData(TYPE_LYCEUM, IN_PROGRESS);
}
// Check if the opposite brazier is lit - if it is, open the gates.
if ((go->GetGUID() == northBrazier->GetGUID() && southBrazier->GetGoState() == GO_STATE_ACTIVE) || (go->GetGUID() == southBrazier->GetGUID() && northBrazier->GetGoState() == GO_STATE_ACTIVE))
{
instance->SetData(TYPE_LYCEUM, DONE);
}
return false;
}
return false;
};
};
class ironhand_guardian : public CreatureScript
{
public:
ironhand_guardian() : CreatureScript("brd_ironhand_guardian") {}
CreatureAI* GetAI(Creature* creature) const override
{
return GetBlackrockDepthsAI<ironhand_guardianAI>(creature);
}
struct ironhand_guardianAI : public CreatureAI
{
ironhand_guardianAI(Creature* creature) : CreatureAI(creature) {}
bool flames_enabled = false;
void SetData(uint32 id, uint32 value) override
{
if (id == 0)
{
if (value == 0 || value == 1)
{
flames_enabled = (bool) (value);
events.ScheduleEvent(SPELL_GOUT_OF_FLAMES, urand(1, IRONHAND_N_GROUPS) * IRONHAND_FLAMES_TIMER / IRONHAND_N_GROUPS);
}
}
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
if (flames_enabled)
{
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case SPELL_GOUT_OF_FLAMES:
DoCast(SPELL_GOUT_OF_FLAMES);
events.RescheduleEvent(SPELL_GOUT_OF_FLAMES, urand(IRONHAND_FLAMES_TIMER - IRONHAND_FLAMES_TIMER_RAND, IRONHAND_FLAMES_TIMER + IRONHAND_FLAMES_TIMER_RAND));
break;
default:
break;
}
}
}
}
EventMap events;
};
};
enum eChallenge
struct Wave
{
QUEST_THE_CHALLENGE = 9015,
GO_BANNER_OF_PROVOCATION = 181058,
GO_ARENA_SPOILS = 181074,
NPC_GRIMSTONE = 10096,
NPC_THELDREN = 16059,
uint32 entry;
uint32 amount;
};
uint32 theldrenTeam[] =
static Wave RingMobs[] = // different amounts based on the type
{
16053, 16055, 16050, 16051, 16049, 16052, 16054, 16058
};
uint32 RingMob[] =
{
8925, // Dredge Worm
8926, // Deep Stinger
8927, // Dark Screecher
8928, // Burrowing Thundersnout
8933, // Cave Creeper
8932, // Borer Beetle
};
{NPC_DREDGE_WORM, 3},
{NPC_DEEP_STINGER, 3},
{NPC_DARK_SCREECHER, 3},
{NPC_THUNDERSNOUT, 2},
{NPC_CAVE_CREEPER, 3},
{NPC_BORER_BEETLE, 6}};
uint32 RingBoss[] =
{
9027, // Gorosh
9028, // Grizzle
9029, // Eviscerator
9030, // Ok'thor
9031, // Anub'shiah
9032, // Hedrum
NPC_GOROSH,
NPC_GRIZZLE,
NPC_EVISCERATOR,
NPC_OKTHOR,
NPC_ANUBSHIAH,
NPC_HEDRUM
};
class at_ring_of_law : public AreaTriggerScript
@@ -119,13 +154,18 @@ public:
{
if (InstanceScript* instance = player->GetInstanceScript())
{
time_t now = time(nullptr);
if (instance->GetData(TYPE_RING_OF_LAW) == IN_PROGRESS || instance->GetData(TYPE_RING_OF_LAW) == DONE)
{
return false;
}
if (now - instance->GetData(DATA_TIME_RING_FAIL) < 2 * 60) // in case of wipe, so people can rez.
{
return false;
}
instance->SetData(TYPE_RING_OF_LAW, IN_PROGRESS);
player->SummonCreature(NPC_GRIMSTONE, 625.559f, -205.618f, -52.735f, 2.609f, TEMPSUMMON_DEAD_DESPAWN, 0);
return false;
return true;
}
return false;
}
@@ -157,9 +197,11 @@ public:
npc_grimstoneAI(Creature* creature) : npc_escortAI(creature), summons(me)
{
instance = creature->GetInstanceScript();
MobSpawnId = rand() % 6;
MobSpawnId = instance ? instance->GetData(DATA_ARENA_MOBS) : urand(0, 5);
BossSpawnId = instance ? instance->GetData(DATA_ARENA_BOSS) : urand(0, 5);
eventPhase = 0;
eventTimer = 1000;
resetTimer = 0;
theldrenEvent = false;
summons.DespawnAll();
}
@@ -169,7 +211,9 @@ public:
uint8 eventPhase;
uint32 eventTimer;
uint32 resetTimer;
uint8 MobSpawnId;
uint8 BossSpawnId;
bool theldrenEvent;
void Reset() override
@@ -189,7 +233,10 @@ public:
summons.Despawn(summon);
// All Summons killed, next phase
if (summons.empty())
{
resetTimer = 0;
eventTimer = 5000;
}
}
void WaypointReached(uint32 waypointId) override
@@ -243,7 +290,45 @@ public:
me->SummonCreature(theldrenTeam[i], 644.300f, -175.989f, -53.739f, 3.418f, TEMPSUMMON_DEAD_DESPAWN, 0);
}
else
me->SummonCreature(RingBoss[rand() % 6], 644.300f, -175.989f, -53.739f, 3.418f, TEMPSUMMON_DEAD_DESPAWN, 0);
me->SummonCreature(RingBoss[BossSpawnId], 644.300f, -175.989f, -53.739f, 3.418f, TEMPSUMMON_DEAD_DESPAWN, 0);
resetTimer = 30000;
}
bool updateReset(uint32 diff)
{
// as long as the summoned creatures have someone to attack, we reset the timer.
// once they don't find anyone, the timer will count down until it is smaller than diff and reset.
bool doReset = false;
if (resetTimer > 0)
{
for (const auto& sum : summons)
{
if (Creature* creature = ObjectAccessor::GetCreature(*me, sum))
{
if (creature->IsAlive() && creature->GetVictim())
{
resetTimer = 30000;
break; // only need to find one.
}
}
}
resetTimer -= diff;
if (resetTimer <= diff)
{
doReset = true;
}
}
return doReset;
}
void SpawnWave(uint32 mobId)
{
for (uint32 i = 0; i < RingMobs[mobId].amount; i++)
{
me->SummonCreature(RingMobs[mobId].entry, 608.960f + 0.4f * i, -235.322f, -53.907f, 1.857f, TEMPSUMMON_DEAD_DESPAWN, 0);
}
resetTimer = 30000;
}
void UpdateEscortAI(uint32 diff) override
@@ -251,6 +336,17 @@ public:
if (!instance)
return;
// reset if our mobs don't have a target.
if (updateReset(diff))
{
summons.DespawnAll();
HandleGameObject(DATA_ARENA4, true);
HandleGameObject(DATA_ARENA3, false);
HandleGameObject(DATA_ARENA2, false);
HandleGameObject(DATA_ARENA1, false);
instance->SetData(TYPE_RING_OF_LAW, FAIL);
}
if (eventTimer)
{
if (eventTimer <= diff)
@@ -277,35 +373,30 @@ public:
case 4:
SetEscortPaused(false);
me->SetVisible(false);
me->SummonCreature(RingMob[MobSpawnId], 608.960f, -235.322f, -53.907f, 1.857f, TEMPSUMMON_DEAD_DESPAWN, 0);
eventTimer = 8000;
SpawnWave(MobSpawnId); // wave 1
eventTimer = 15000;
break;
case 5:
me->SummonCreature(RingMob[MobSpawnId], 608.960f, -235.322f, -53.907f, 1.857f, TEMPSUMMON_DEAD_DESPAWN, 0);
me->SummonCreature(RingMob[MobSpawnId], 608.960f, -235.322f, -53.907f, 1.857f, TEMPSUMMON_DEAD_DESPAWN, 0);
eventTimer = 8000;
SpawnWave(MobSpawnId); // wave 2
eventTimer = 0; // will be set from SummonedCreatureDies
break;
case 6:
me->SummonCreature(RingMob[MobSpawnId], 608.960f, -235.322f, -53.907f, 1.857f, TEMPSUMMON_DEAD_DESPAWN, 0);
eventTimer = 0;
break;
case 7:
me->SetVisible(true);
HandleGameObject(DATA_ARENA1, false);
Talk(SAY_TEXT6);
SetEscortPaused(false);
eventTimer = 0;
break;
case 8:
case 7:
HandleGameObject(DATA_ARENA2, true);
eventTimer = 5000;
break;
case 9:
case 8:
me->SetVisible(false);
SummonBoss();
eventTimer = 0;
break;
case 10:
case 9:
if (theldrenEvent)
{
if (GameObject* go = me->SummonGameObject(GO_ARENA_SPOILS, 596.48f, -187.91f, -54.14f, 4.9f, 0.0f, 0.0f, 0.0f, 0.0f, 300))
@@ -614,4 +705,5 @@ void AddSC_blackrock_depths()
new npc_phalanx();
new npc_lokhtos_darkbargainer();
new npc_rocknot();
new ironhand_guardian();
}

View File

@@ -21,6 +21,13 @@
#include "CreatureAIImpl.h"
#define BRDScriptName "instance_blackrock_depths"
enum FactionIds
{
FACTION_NEUTRAL = 674,
FACTION_HOSTILE = 754,
FACTION_FRIEND = 35
};
enum BRDBosses
{
BOSS_AMBASSADOR_FLAMELASH = 0,
@@ -56,22 +63,86 @@ enum DataTypes
DATA_SF_BRAZIER_N = 25,
DATA_SF_BRAZIER_S = 26,
DATA_MOIRA = 27,
DATA_PRIESTESS = 28,
DATA_OPEN_COFFER_DOORS = 30,
DATA_GOLEM_LORD_ARGELMACH_INIT = 31,
DATA_GOLEM_LORD_ARGELMACH_ADDS = 32,
DATA_MAGMUS = 33,
DATA_COREN = 34
DATA_COREN = 34,
DATA_ANUBSHIAH,
DATA_EVISCERATOR,
DATA_GOROSH,
DATA_GRIZZLE,
DATA_HEDRUM,
DATA_OKTHOR,
DATA_TIME_RING_FAIL,
DATA_ARENA_MOBS,
DATA_ARENA_BOSS
};
enum CreatureIds
enum Creatures
{
NPC_MAGMUS = 9938
NPC_EMPEROR = 9019,
NPC_PHALANX = 9502,
NPC_ANGERREL = 9035,
NPC_DOPEREL = 9040,
NPC_HATEREL = 9034,
NPC_VILEREL = 9036,
NPC_SEETHREL = 9038,
NPC_GLOOMREL = 9037,
NPC_DOOMREL = 9039,
NPC_MOIRA = 8929,
NPC_PRIESTESS = 10076,
NPC_WATCHMAN_DOOMGRIP = 9476,
NPC_WEAPON_TECHNICIAN = 8920,
NPC_DOOMFORGE_ARCANASMITH = 8900,
NPC_RAGEREAVER_GOLEM = 8906,
NPC_WRATH_HAMMER_CONSTRUCT = 8907,
NPC_GOLEM_LORD_ARGELMACH = 8983,
NPC_COREN_DIREBREW = 23872,
NPC_IRONHAND_GUARDIAN = 8982,
NPC_ARENA_SPECTATOR = 8916,
NPC_SHADOWFORGE_PEASANT = 8896,
NPC_SHADOWFORCE_CITIZEN = 8902,
NPC_SHADOWFORGE_SENATOR = 8904,
NPC_MAGMUS = 9938,
NPC_DREDGE_WORM = 8925,
NPC_DEEP_STINGER = 8926,
NPC_DARK_SCREECHER = 8927,
NPC_THUNDERSNOUT = 8928,
NPC_BORER_BEETLE = 8932,
NPC_CAVE_CREEPER = 8933,
NPC_GOROSH = 9027,
NPC_GRIZZLE = 9028,
NPC_EVISCERATOR = 9029,
NPC_OKTHOR = 9030,
NPC_ANUBSHIAH = 9031,
NPC_HEDRUM = 9032
};
enum eChallenge
{
QUEST_THE_CHALLENGE = 9015,
GO_BANNER_OF_PROVOCATION = 181058,
GO_ARENA_SPOILS = 181074,
NPC_GRIMSTONE = 10096,
NPC_THELDREN = 16059,
};
const uint32 theldrenTeam[] = {16053, 16055, 16050, 16051, 16049, 16052, 16054, 16058};
template <class AI, class T>
inline AI* GetBlackrockDepthsAI(T* obj)
{

View File

@@ -21,11 +21,20 @@
enum Spells
{
SPELL_SHADOWBOLT = 17228,
SPELL_CURSEOFTONGUES = 15470,
SPELL_CURSEOFWEAKNESS = 17227,
SPELL_DEMONARMOR = 11735,
SPELL_ENVELOPINGWEB = 15471
SPELL_SHADOWBOLT = 15472,
SPELL_CURSE_TONGUES = 15470,
SPELL_CURSE_WEAKNESS = 12493,
SPELL_DEMON_ARMOR = 13787,
SPELL_ENVELOPING_WEB = 15471
};
enum Timers
{
TIMER_SHADOWBOLT = 7000,
TIMER_CURSE_TONGUES = 24000,
TIMER_CURSE_WEAKNESS = 12000,
TIMER_DEMON_ARMOR = 3000, // virtually only cast once
TIMER_ENVELOPING_WEB = 16000
};
class boss_anubshiah : public CreatureScript
@@ -38,75 +47,68 @@ public:
return GetBlackrockDepthsAI<boss_anubshiahAI>(creature);
}
struct boss_anubshiahAI : public ScriptedAI
struct boss_anubshiahAI : public BossAI
{
boss_anubshiahAI(Creature* creature) : ScriptedAI(creature) { }
boss_anubshiahAI(Creature* creature) : BossAI(creature, DATA_ANUBSHIAH) { }
uint32 ShadowBolt_Timer;
uint32 CurseOfTongues_Timer;
uint32 CurseOfWeakness_Timer;
uint32 DemonArmor_Timer;
uint32 EnvelopingWeb_Timer;
void Reset() override
void EnterCombat(Unit* /*who*/) override
{
ShadowBolt_Timer = 7000;
CurseOfTongues_Timer = 24000;
CurseOfWeakness_Timer = 12000;
DemonArmor_Timer = 3000;
EnvelopingWeb_Timer = 16000;
_EnterCombat();
events.ScheduleEvent(SPELL_SHADOWBOLT, 0.2 * (int)TIMER_SHADOWBOLT);
events.ScheduleEvent(SPELL_CURSE_TONGUES, 0.2 * (int)TIMER_CURSE_TONGUES);
events.ScheduleEvent(SPELL_CURSE_WEAKNESS, 0.2 * (int)TIMER_CURSE_WEAKNESS);
events.ScheduleEvent(SPELL_DEMON_ARMOR, 0.2 * (int)TIMER_DEMON_ARMOR);
events.ScheduleEvent(SPELL_ENVELOPING_WEB, 0.2 * (int)TIMER_ENVELOPING_WEB);
}
void EnterCombat(Unit* /*who*/) override { }
void UpdateAI(uint32 diff) override
{
//Return since we have no target
if (!UpdateVictim())
{
return;
//ShadowBolt_Timer
if (ShadowBolt_Timer <= diff)
{
DoCastVictim(SPELL_SHADOWBOLT);
ShadowBolt_Timer = 7000;
}
else ShadowBolt_Timer -= diff;
events.Update(diff);
//CurseOfTongues_Timer
if (CurseOfTongues_Timer <= diff)
if (me->HasUnitState(UNIT_STATE_CASTING))
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(target, SPELL_CURSEOFTONGUES);
CurseOfTongues_Timer = 18000;
return;
}
else CurseOfTongues_Timer -= diff;
//CurseOfWeakness_Timer
if (CurseOfWeakness_Timer <= diff)
while (uint32 eventId = events.ExecuteEvent())
{
DoCastVictim(SPELL_CURSEOFWEAKNESS);
CurseOfWeakness_Timer = 45000;
switch (eventId)
{
case SPELL_SHADOWBOLT:
DoCastVictim(SPELL_SHADOWBOLT);
events.ScheduleEvent(SPELL_SHADOWBOLT, urand(TIMER_SHADOWBOLT - 2000, TIMER_SHADOWBOLT + 2000));
break;
case SPELL_CURSE_TONGUES:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
{
DoCast(target, SPELL_CURSE_TONGUES);
}
events.ScheduleEvent(SPELL_CURSE_TONGUES, urand(TIMER_CURSE_TONGUES - 2000, TIMER_CURSE_TONGUES + 2000));
break;
case SPELL_CURSE_WEAKNESS:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
{
DoCast(target, SPELL_CURSE_WEAKNESS);
}
events.ScheduleEvent(SPELL_CURSE_WEAKNESS, urand(TIMER_CURSE_WEAKNESS - 2000, TIMER_CURSE_WEAKNESS + 2000));
break;
case SPELL_DEMON_ARMOR:
DoCast(me, SPELL_DEMON_ARMOR);
events.ScheduleEvent(SPELL_DEMON_ARMOR, TIMER_DEMON_ARMOR);
break;
case SPELL_ENVELOPING_WEB:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(target, SPELL_ENVELOPING_WEB);
events.ScheduleEvent(SPELL_ENVELOPING_WEB, urand(TIMER_ENVELOPING_WEB - 2000, TIMER_ENVELOPING_WEB + 2000));
break;
default:
break;
}
}
else CurseOfWeakness_Timer -= diff;
//DemonArmor_Timer
if (DemonArmor_Timer <= diff)
{
DoCast(me, SPELL_DEMONARMOR);
DemonArmor_Timer = 300000;
}
else DemonArmor_Timer -= diff;
//EnvelopingWeb_Timer
if (EnvelopingWeb_Timer <= diff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(target, SPELL_ENVELOPINGWEB);
EnvelopingWeb_Timer = 12000;
}
else EnvelopingWeb_Timer -= diff;
DoMeleeAttackIfReady();
}
};

View File

@@ -21,16 +21,19 @@
enum Yells
{
SAY_AGGRO = 0,
SAY_SLAY = 1
YELL_SENATORS_ALIVE = 0,
YELL_SENATORS_DEAD = 1,
SAY_SLAY = 2
};
enum Spells
{
SPELL_HANDOFTHAURISSAN = 17492,
SPELL_AVATAROFFLAME = 15636
SPELL_HANDOFTHAURISSAN = 17492,
SPELL_AVATAROFFLAME = 15636
};
#define DATA_PERCENT_DEAD_SENATORS 0
class boss_emperor_dagran_thaurissan : public CreatureScript
{
public:
@@ -41,29 +44,27 @@ public:
return GetBlackrockDepthsAI<boss_draganthaurissanAI>(creature);
}
struct boss_draganthaurissanAI : public ScriptedAI
struct boss_draganthaurissanAI : public BossAI
{
boss_draganthaurissanAI(Creature* creature) : ScriptedAI(creature)
{
instance = me->GetInstanceScript();
}
uint32 hasYelled = 0;
uint32 SenatorYells[5] = {3, 4, 5, 6, 7}; // IDs in creature_text database
InstanceScript* instance;
uint32 HandOfThaurissan_Timer;
uint32 AvatarOfFlame_Timer;
//uint32 Counter;
void Reset() override
{
HandOfThaurissan_Timer = 4000;
AvatarOfFlame_Timer = 25000;
//Counter= 0;
}
boss_draganthaurissanAI(Creature* creature) : BossAI(creature, DATA_EMPEROR){}
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
if (hasYelled != 5)
{
Talk(YELL_SENATORS_ALIVE);
}
else
{
Talk(YELL_SENATORS_DEAD);
}
me->CallForHelp(VISIBLE_RANGE);
events.ScheduleEvent(SPELL_HANDOFTHAURISSAN, urand(4000, 7000));
events.ScheduleEvent(SPELL_AVATAROFFLAME, urand(10000, 12000));
}
void KilledUnit(Unit* /*victim*/) override
@@ -71,11 +72,27 @@ public:
Talk(SAY_SLAY);
}
void SetData(uint32 type, uint32 data) override
{
if (type == DATA_PERCENT_DEAD_SENATORS)
{
if (data >= 20 * (hasYelled + 1)) // map the 5 yells to %. Yell after 20,40,60,80,100%
{
if (hasYelled < 5)
{
Talk(SenatorYells[hasYelled]);
}
hasYelled++;
}
}
}
void JustDied(Unit* /*killer*/) override
{
if (Creature* Moira = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MOIRA)))
{
Moira->AI()->EnterEvadeMode();
Moira->AI()->Talk(0);
Moira->SetFaction(FACTION_FRIENDLY);
}
}
@@ -86,33 +103,28 @@ public:
if (!UpdateVictim())
return;
if (HandOfThaurissan_Timer <= diff)
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_HANDOFTHAURISSAN);
//3 Hands of Thaurissan will be cast
//if (Counter < 3)
//{
// HandOfThaurissan_Timer = 1000;
// ++Counter;
//}
//else
//{
HandOfThaurissan_Timer = 5000;
//Counter = 0;
//}
switch (eventId)
{
case SPELL_HANDOFTHAURISSAN:
DoCast(SelectTarget(SELECT_TARGET_RANDOM), SPELL_HANDOFTHAURISSAN);
//DoCastVictim(SPELL_HANDOFTHAURISSAN);
events.ScheduleEvent(SPELL_HANDOFTHAURISSAN, urand(4000, 7000));
break;
case SPELL_AVATAROFFLAME:
DoCastSelf(SPELL_AVATAROFFLAME);
events.ScheduleEvent(SPELL_AVATAROFFLAME, urand(23000, 27000));
break;
default:
break;
}
}
else HandOfThaurissan_Timer -= diff;
//AvatarOfFlame_Timer
if (AvatarOfFlame_Timer <= diff)
{
DoCastVictim(SPELL_AVATAROFFLAME);
AvatarOfFlame_Timer = 18000;
}
else AvatarOfFlame_Timer -= diff;
DoMeleeAttackIfReady();
}
};

View File

@@ -0,0 +1,110 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "blackrock_depths.h"
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
enum Spells
{
SPELL_SHADOWBOLT_VOLLEY = 15245,
SPELL_REND = 14331,
SPELL_SHIELD = 7121
};
enum Timers
{
TIMER_SHADOWBOLT_VOLLEY = 7000,
TIMER_REND = 20000,
TIMER_SHIELD = 12000
};
class boss_eviscerator : public CreatureScript
{
public:
boss_eviscerator() : CreatureScript("boss_eviscerator") {}
CreatureAI* GetAI(Creature* creature) const override
{
return GetBlackrockDepthsAI<boss_evisceratorAI>(creature);
}
struct boss_evisceratorAI : public BossAI
{
boss_evisceratorAI(Creature* creature) : BossAI(creature, DATA_EVISCERATOR) {}
bool SpellShieldReady = false;
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
events.ScheduleEvent(SPELL_SHADOWBOLT_VOLLEY, 0.2 * (int)TIMER_SHADOWBOLT_VOLLEY);
events.ScheduleEvent(SPELL_REND, 0.2 * (int) TIMER_REND);
events.ScheduleEvent(SPELL_SHIELD, 0.2 * (int) TIMER_SHIELD);
}
void DamageTaken(Unit* /* doneBy */, uint32& /* damage */, DamageEffectType /* damagetype */, SpellSchoolMask damageSchoolMask) override
{
if ((damageSchoolMask & SPELL_SCHOOL_MASK_MAGIC) && SpellShieldReady)
{
DoCast(SPELL_SHIELD);
SpellShieldReady = false;
events.ScheduleEvent(SPELL_SHIELD, TIMER_SHIELD);
}
}
void UpdateAI(uint32 diff) override
{
//Return since we have no target
if (!UpdateVictim())
{
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case SPELL_SHADOWBOLT_VOLLEY:
DoCastVictim(SPELL_SHADOWBOLT_VOLLEY);
events.ScheduleEvent(SPELL_SHADOWBOLT_VOLLEY, urand(TIMER_SHADOWBOLT_VOLLEY - 2000, TIMER_SHADOWBOLT_VOLLEY + 2000));
break;
case SPELL_REND:
DoCastVictim(SPELL_REND);
events.ScheduleEvent(SPELL_REND, urand(TIMER_REND - 2000, TIMER_REND + 2000));
break;
case SPELL_SHIELD:
SpellShieldReady = true;
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
};
};
void AddSC_boss_eviscerator()
{
new boss_eviscerator();
}

View File

@@ -21,8 +21,16 @@
enum Spells
{
SPELL_WHIRLWIND = 15589,
SPELL_MORTALSTRIKE = 24573
SPELL_WHIRLWIND = 15589,
SPELL_MORTALSTRIKE = 15708,
SPELL_BLOODLUST = 21049
};
enum Timers
{
TIMER_WHIRLWIND = 12000,
TIMER_MORTAL = 22000,
TIMER_BLOODLUST = 30000
};
class boss_gorosh_the_dervish : public CreatureScript
@@ -35,45 +43,62 @@ public:
return GetBlackrockDepthsAI<boss_gorosh_the_dervishAI>(creature);
}
struct boss_gorosh_the_dervishAI : public ScriptedAI
struct boss_gorosh_the_dervishAI : public BossAI
{
boss_gorosh_the_dervishAI(Creature* creature) : ScriptedAI(creature) { }
boss_gorosh_the_dervishAI(Creature* creature) : BossAI(creature, DATA_GOROSH) { }
uint32 WhirlWind_Timer;
uint32 MortalStrike_Timer;
void Reset() override
{
WhirlWind_Timer = 12000;
MortalStrike_Timer = 22000;
}
uint32 nextWhirlwindTime;
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
events.ScheduleEvent(SPELL_WHIRLWIND, 0.2 * (int) TIMER_WHIRLWIND);
events.ScheduleEvent(SPELL_MORTALSTRIKE, 0.2 * (int) TIMER_MORTAL);
events.ScheduleEvent(SPELL_BLOODLUST, 0.2 * (int) TIMER_BLOODLUST);
}
void UpdateAI(uint32 diff) override
{
//Return since we have no target
// Return since we have no target
if (!UpdateVictim())
{
return;
//WhirlWind_Timer
if (WhirlWind_Timer <= diff)
{
DoCast(me, SPELL_WHIRLWIND);
WhirlWind_Timer = 15000;
}
else WhirlWind_Timer -= diff;
events.Update(diff);
//MortalStrike_Timer
if (MortalStrike_Timer <= diff)
if (me->HasUnitState(UNIT_STATE_CASTING))
{
DoCastVictim(SPELL_MORTALSTRIKE);
MortalStrike_Timer = 15000;
return;
}
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case SPELL_WHIRLWIND:
if (me->GetDistance2d(me->GetVictim()) < 10.0f)
{
DoCastVictim(SPELL_WHIRLWIND);
nextWhirlwindTime = urand(TIMER_WHIRLWIND - 2000, TIMER_WHIRLWIND + 2000);
}
else
{
// reschedule sooner
nextWhirlwindTime = 0.3 * urand(TIMER_WHIRLWIND - 2000, TIMER_WHIRLWIND + 2000);
}
events.ScheduleEvent(SPELL_WHIRLWIND, nextWhirlwindTime);
break;
case SPELL_MORTALSTRIKE:
DoCastVictim(SPELL_MORTALSTRIKE);
events.ScheduleEvent(SPELL_MORTALSTRIKE, urand(TIMER_MORTAL - 2000, TIMER_MORTAL + 2000));
break;
case SPELL_BLOODLUST:
DoCastSelf(SPELL_BLOODLUST);
events.ScheduleEvent(SPELL_BLOODLUST, urand(TIMER_BLOODLUST - 2000, TIMER_BLOODLUST + 2000));
break;
default:
break;
}
}
else MortalStrike_Timer -= diff;
DoMeleeAttackIfReady();
}
};

View File

@@ -22,10 +22,16 @@
enum Grizzle
{
SPELL_GROUNDTREMOR = 6524,
SPELL_FRENZY = 28371,
SPELL_FRENZY = 8269,
EMOTE_FRENZY_KILL = 0
};
enum Timer
{
TIMER_GROUNDTREMOR = 10000,
TIMER_FRENZY = 15000
};
class boss_grizzle : public CreatureScript
{
public:
@@ -36,48 +42,58 @@ public:
return GetBlackrockDepthsAI<boss_grizzleAI>(creature);
}
struct boss_grizzleAI : public ScriptedAI
struct boss_grizzleAI : public BossAI
{
boss_grizzleAI(Creature* creature) : ScriptedAI(creature) { }
boss_grizzleAI(Creature* creature) : BossAI(creature, DATA_GRIZZLE) {}
uint32 GroundTremor_Timer;
uint32 Frenzy_Timer;
uint32 nextTremorTime;
void Reset() override
void EnterCombat(Unit* /*who*/) override
{
GroundTremor_Timer = 12000;
Frenzy_Timer = 0;
_EnterCombat();
events.ScheduleEvent(SPELL_GROUNDTREMOR, 0.2 * (int) TIMER_GROUNDTREMOR);
events.ScheduleEvent(SPELL_FRENZY, 0.2 * (int) TIMER_FRENZY);
}
void EnterCombat(Unit* /*who*/) override { }
void UpdateAI(uint32 diff) override
{
//Return since we have no target
if (!UpdateVictim())
{
return;
//GroundTremor_Timer
if (GroundTremor_Timer <= diff)
{
DoCastVictim(SPELL_GROUNDTREMOR);
GroundTremor_Timer = 8000;
}
else GroundTremor_Timer -= diff;
events.Update(diff);
//Frenzy_Timer
if (HealthBelowPct(51))
if (me->HasUnitState(UNIT_STATE_CASTING))
{
if (Frenzy_Timer <= diff)
return;
}
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
DoCast(me, SPELL_FRENZY);
case SPELL_GROUNDTREMOR:
if (me->GetDistance2d(me->GetVictim()) < 10.0f)
{
DoCastVictim(SPELL_GROUNDTREMOR);
nextTremorTime = urand(TIMER_GROUNDTREMOR - 2000, TIMER_GROUNDTREMOR + 2000);
}
else
{
nextTremorTime = 0.3*urand(TIMER_GROUNDTREMOR - 2000, TIMER_GROUNDTREMOR + 2000);
}
events.ScheduleEvent(SPELL_GROUNDTREMOR, nextTremorTime);
break;
case SPELL_FRENZY:
DoCastSelf(SPELL_FRENZY);
events.ScheduleEvent(SPELL_FRENZY, urand(TIMER_FRENZY - 2000, TIMER_FRENZY + 2000));
Talk(EMOTE_FRENZY_KILL);
Frenzy_Timer = 15000;
break;
default:
break;
}
else Frenzy_Timer -= diff;
}
DoMeleeAttackIfReady();
}
};

View File

@@ -0,0 +1,102 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "blackrock_depths.h"
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
enum Spells
{
SPELL_PARALYZING = 3609,
SPELL_BANEFUL = 15475,
SPELL_WEB_EXPLOSION = 15474
};
enum Timers
{
TIMER_PARALYZING = 20000,
TIMER_BANEFUL = 24000,
TIMER_WEB_EXPLOSION = 20000
};
class boss_hedrum : public CreatureScript
{
public:
boss_hedrum() : CreatureScript("boss_hedrum") {}
CreatureAI* GetAI(Creature* creature) const override
{
return GetBlackrockDepthsAI<boss_hedrumAI>(creature);
}
struct boss_hedrumAI : public BossAI
{
boss_hedrumAI(Creature* creature) : BossAI(creature, DATA_HEDRUM) {}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
events.ScheduleEvent(SPELL_PARALYZING, 0.2 * (int) TIMER_PARALYZING);
events.ScheduleEvent(SPELL_BANEFUL, 0.2 * (int) TIMER_BANEFUL);
events.ScheduleEvent(SPELL_WEB_EXPLOSION, 0.2 * (int) TIMER_WEB_EXPLOSION);
}
void UpdateAI(uint32 diff) override
{
// Return since we have no target
if (!UpdateVictim())
{
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case SPELL_PARALYZING:
DoCastVictim(SPELL_PARALYZING);
events.ScheduleEvent(SPELL_PARALYZING, urand(TIMER_PARALYZING - 2000, TIMER_PARALYZING + 2000));
break;
case SPELL_BANEFUL:
DoCastVictim(SPELL_BANEFUL);
events.ScheduleEvent(SPELL_BANEFUL, urand(TIMER_BANEFUL - 2000, TIMER_BANEFUL + 2000));
break;
case SPELL_WEB_EXPLOSION:
if (me->GetDistance2d(me->GetVictim()) < 100.0f)
{
DoCast(SPELL_WEB_EXPLOSION);
}
events.ScheduleEvent(SPELL_WEB_EXPLOSION, urand(TIMER_WEB_EXPLOSION - 2000, TIMER_WEB_EXPLOSION + 2000));
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
};
};
void AddSC_boss_hedrum()
{
new boss_hedrum();
}

View File

@@ -25,6 +25,14 @@ enum Spells
SPELL_WARSTOMP = 24375
};
enum SpellTimers
{
SPELL_FIERYBURST_MIN = 4000,
SPELL_FIERYBURST_MAX = 8000,
SPELL_WARSTOMP_MIN = 8000,
SPELL_WARSTOMP_MAX = 12000
};
class boss_magmus : public CreatureScript
{
public:
@@ -35,54 +43,53 @@ public:
return GetBlackrockDepthsAI<boss_magmusAI>(creature);
}
struct boss_magmusAI : public ScriptedAI
struct boss_magmusAI : public BossAI
{
boss_magmusAI(Creature* creature) : ScriptedAI(creature) { }
uint32 FieryBurst_Timer;
uint32 WarStomp_Timer;
boss_magmusAI(Creature* creature) : BossAI(creature, TYPE_IRON_HALL) {}
void Reset() override
{
FieryBurst_Timer = 5000;
WarStomp_Timer = 0;
_Reset();
instance->SetData(TYPE_IRON_HALL, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/) override { }
void EnterCombat(Unit* /*who*/) override
{
instance->SetData(TYPE_IRON_HALL, IN_PROGRESS);
_EnterCombat();
events.ScheduleEvent(SPELL_FIERYBURST, urand(SPELL_FIERYBURST_MIN, SPELL_FIERYBURST_MAX));
events.ScheduleEvent(SPELL_WARSTOMP, urand(SPELL_WARSTOMP_MIN, SPELL_WARSTOMP_MAX));
}
void UpdateAI(uint32 diff) override
{
//Return since we have no target
if (!UpdateVictim())
{
return;
//FieryBurst_Timer
if (FieryBurst_Timer <= diff)
{
DoCastVictim(SPELL_FIERYBURST);
FieryBurst_Timer = 6000;
}
else FieryBurst_Timer -= diff;
events.Update(diff);
//WarStomp_Timer
if (HealthBelowPct(51))
while (uint32 eventId = events.ExecuteEvent())
{
if (WarStomp_Timer <= diff)
switch (eventId)
{
case SPELL_WARSTOMP:
DoCastVictim(SPELL_WARSTOMP);
WarStomp_Timer = 8000;
events.ScheduleEvent(SPELL_WARSTOMP, urand(SPELL_WARSTOMP_MIN, SPELL_WARSTOMP_MAX));
break;
case SPELL_FIERYBURST:
DoCastVictim(SPELL_FIERYBURST);
events.ScheduleEvent(SPELL_FIERYBURST, urand(SPELL_FIERYBURST_MIN, SPELL_FIERYBURST_MAX));
break;
default:
break;
}
else WarStomp_Timer -= diff;
}
DoMeleeAttackIfReady();
}
// When he die open door to last chamber
void JustDied(Unit* killer) override
{
if (InstanceScript* instance = killer->GetInstanceScript())
instance->HandleGameObject(instance->GetGuidData(DATA_THRONE_DOOR), true);
}
};
};

View File

@@ -21,12 +21,134 @@
enum Spells
{
SPELL_HEAL = 10917,
SPELL_RENEW = 10929,
SPELL_SHIELD = 10901,
SPELL_MINDBLAST = 10947,
SPELL_SHADOWWORDPAIN = 10894,
SPELL_SMITE = 10934
SPELL_HEAL = 15586,
SPELL_RENEW = 8362,
SPELL_MINDBLAST = 15587,
SPELL_SHADOWBOLT = 15537,
SPELL_WORDPAIN = 15654,
};
enum SpellTimers
{
TIMER_HEAL = 12000,
TIMER_MINDBLAST = 16000,
TIMER_RENEW = 12000,
TIMER_SHADOWBOLT = 16000,
TIMER_WORDPAIN = 12000,
};
struct boss_moira_bronzebeardAI : public BossAI
{
// use a default value so we can inherit for priestess
boss_moira_bronzebeardAI(Creature* creature, uint32 data = DATA_MOIRA) : BossAI(creature, data) {}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
events.ScheduleEvent(SPELL_MINDBLAST, 0.5 * (int) TIMER_MINDBLAST);
events.ScheduleEvent(SPELL_HEAL, 0.5 * (int) TIMER_HEAL);
events.ScheduleEvent(SPELL_RENEW, 0.5 * (int) TIMER_RENEW);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
{
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case SPELL_MINDBLAST:
DoCastVictim(SPELL_MINDBLAST);
events.ScheduleEvent(SPELL_MINDBLAST, urand(TIMER_MINDBLAST - 2000, TIMER_MINDBLAST + 2000));
break;
case SPELL_HEAL:
CastOnEmperorIfPossible(SPELL_HEAL, TIMER_HEAL);
break;
case SPELL_RENEW:
CastOnEmperorIfPossible(SPELL_RENEW, TIMER_RENEW);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
void CastOnEmperorIfPossible(uint32 spell, uint32 timer)
{
Creature* emperor = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EMPEROR));
if (emperor && emperor->HealthBelowPct(90))
{
DoCast(emperor, spell);
}
else if (HealthBelowPct(90))
{
DoCastSelf(spell);
}
events.ScheduleEvent(spell, urand(timer - 2000, timer + 2000));
}
};
// high priestess should be fairly identical to Moira.
// Running away when emperor dies is handled through GUID from emperor, therefore not relevant here.
struct boss_high_priestess_thaurissanAI : public boss_moira_bronzebeardAI
{
boss_high_priestess_thaurissanAI(Creature* creature) : boss_moira_bronzebeardAI(creature, DATA_PRIESTESS) {}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
Talk(0);
events.ScheduleEvent(SPELL_WORDPAIN, 0.5 * (int)TIMER_WORDPAIN);
events.ScheduleEvent(SPELL_HEAL, 0.5 * (int) TIMER_HEAL);
events.ScheduleEvent(SPELL_RENEW, 0.5 * (int) TIMER_RENEW);
events.ScheduleEvent(SPELL_SHADOWBOLT, 0.5 * (int) TIMER_SHADOWBOLT);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
{
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case SPELL_WORDPAIN:
DoCastVictim(SPELL_WORDPAIN);
events.ScheduleEvent(SPELL_WORDPAIN, urand(TIMER_WORDPAIN - 2000, TIMER_WORDPAIN + 2000));
break;
case SPELL_HEAL:
CastOnEmperorIfPossible(SPELL_HEAL, TIMER_HEAL);
break;
case SPELL_RENEW:
CastOnEmperorIfPossible(SPELL_RENEW, TIMER_RENEW);
break;
case SPELL_SHADOWBOLT:
DoCastVictim(SPELL_SHADOWBOLT);
events.ScheduleEvent(SPELL_SHADOWBOLT, urand(TIMER_SHADOWBOLT - 2000, TIMER_SHADOWBOLT + 2000));
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
};
class boss_moira_bronzebeard : public CreatureScript
@@ -38,60 +160,25 @@ public:
{
return GetBlackrockDepthsAI<boss_moira_bronzebeardAI>(creature);
}
};
struct boss_moira_bronzebeardAI : public ScriptedAI
class boss_high_priestess_thaurissan : public CreatureScript
{
public:
boss_high_priestess_thaurissan() : CreatureScript("boss_high_priestess_thaurissan") {}
CreatureAI* GetAI(Creature* creature) const override
{
boss_moira_bronzebeardAI(Creature* creature) : ScriptedAI(creature) { }
uint32 Heal_Timer;
uint32 MindBlast_Timer;
uint32 ShadowWordPain_Timer;
uint32 Smite_Timer;
void Reset() override
{
Heal_Timer = 12000; //These times are probably wrong
MindBlast_Timer = 16000;
ShadowWordPain_Timer = 2000;
Smite_Timer = 8000;
}
void EnterCombat(Unit* /*who*/) override { }
void UpdateAI(uint32 diff) override
{
//Return since we have no target
if (!UpdateVictim())
return;
//MindBlast_Timer
if (MindBlast_Timer <= diff)
{
DoCastVictim(SPELL_MINDBLAST);
MindBlast_Timer = 14000;
}
else MindBlast_Timer -= diff;
//ShadowWordPain_Timer
if (ShadowWordPain_Timer <= diff)
{
DoCastVictim(SPELL_SHADOWWORDPAIN);
ShadowWordPain_Timer = 18000;
}
else ShadowWordPain_Timer -= diff;
//Smite_Timer
if (Smite_Timer <= diff)
{
DoCastVictim(SPELL_SMITE);
Smite_Timer = 10000;
}
else Smite_Timer -= diff;
}
};
return GetBlackrockDepthsAI<boss_high_priestess_thaurissanAI>(creature);
}
};
void AddSC_boss_moira_bronzebeard()
{
new boss_moira_bronzebeard();
}
void AddSC_boss_high_priestess_thaurissan()
{
new boss_high_priestess_thaurissan();
}

View File

@@ -0,0 +1,126 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "blackrock_depths.h"
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
enum Spells
{
SPELL_ARCANE_BOLT = 13748,
SPELL_ARCANE_EXPLOSION = 1467,
SPELL_POLYMORPH = 15534,
SPELL_SLOW = 19137
};
enum Timers
{
TIMER_ARCANE_BOLT = 7000,
TIMER_ARCANE_EXPLOSION = 24000,
TIMER_POLYMORPH = 12000,
TIMER_SLOW = 15000
};
class boss_okthor : public CreatureScript
{
public:
boss_okthor() : CreatureScript("boss_okthor") {}
CreatureAI* GetAI(Creature* creature) const override
{
return GetBlackrockDepthsAI<boss_okthorAI>(creature);
}
struct boss_okthorAI : public BossAI
{
boss_okthorAI(Creature* creature) : BossAI(creature, DATA_OKTHOR) {}
uint32 nextArcaneExplosionTime;
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
events.ScheduleEvent(SPELL_ARCANE_BOLT, 0.2 * (int) TIMER_ARCANE_BOLT);
events.ScheduleEvent(SPELL_ARCANE_EXPLOSION, 0.2 * (int) TIMER_ARCANE_EXPLOSION);
events.ScheduleEvent(SPELL_POLYMORPH, 0.2 * (int) TIMER_POLYMORPH);
events.ScheduleEvent(SPELL_SLOW, 500);
}
void UpdateAI(uint32 diff) override
{
//Return since we have no target
if (!UpdateVictim())
{
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case SPELL_ARCANE_BOLT:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
{
DoCast(target, SPELL_ARCANE_BOLT);
}
events.ScheduleEvent(SPELL_ARCANE_BOLT, urand(TIMER_ARCANE_BOLT - 2000, TIMER_ARCANE_BOLT + 2000));
break;
case SPELL_ARCANE_EXPLOSION:
if (me->GetDistance2d(me->GetVictim()) < 50.0f)
{
DoCast(SPELL_ARCANE_EXPLOSION);
nextArcaneExplosionTime = urand(TIMER_ARCANE_EXPLOSION - 2000, TIMER_ARCANE_EXPLOSION + 2000);
}
else
{
nextArcaneExplosionTime = 0.3*urand(TIMER_ARCANE_EXPLOSION - 2000, TIMER_ARCANE_EXPLOSION + 2000);
}
events.ScheduleEvent(SPELL_ARCANE_EXPLOSION, nextArcaneExplosionTime);
break;
case SPELL_POLYMORPH:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
{
DoCast(target, SPELL_POLYMORPH);
}
events.ScheduleEvent(SPELL_POLYMORPH, urand(TIMER_POLYMORPH - 2000, TIMER_POLYMORPH + 2000));
break;
case SPELL_SLOW:
if (me->GetDistance2d(me->GetVictim()) < 50.0f)
{
DoCast(SPELL_SLOW);
}
events.ScheduleEvent(SPELL_SLOW, TIMER_SLOW);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
};
};
void AddSC_boss_okthor()
{
new boss_okthor();
}

View File

@@ -29,28 +29,16 @@ enum Timers
TIMER_TOMB_RESET = 15000
};
enum Creatures
enum Distances
{
NPC_EMPEROR = 9019,
NPC_PHALANX = 9502,
NPC_ANGERREL = 9035,
NPC_DOPEREL = 9040,
NPC_HATEREL = 9034,
NPC_VILEREL = 9036,
NPC_SEETHREL = 9038,
NPC_GLOOMREL = 9037,
NPC_DOOMREL = 9039,
NPC_MOIRA = 8929,
RADIUS_RING_OF_LAW = 80,
DISTANCE_EMPEROR_ROOM = 125
};
NPC_WATCHMAN_DOOMGRIP = 9476,
NPC_WEAPON_TECHNICIAN = 8920,
NPC_DOOMFORGE_ARCANASMITH = 8900,
NPC_RAGEREAVER_GOLEM = 8906,
NPC_WRATH_HAMMER_CONSTRUCT = 8907,
NPC_GOLEM_LORD_ARGELMACH = 8983,
NPC_COREN_DIREBREW = 23872
enum PrincessQuests
{
PRINCESS_QUEST_HORDE = 4004,
PRINCESS_QUEST_ALLIANCE = 4363
};
enum GameObjects
@@ -127,6 +115,8 @@ public:
ObjectGuid PhalanxGUID;
ObjectGuid MagmusGUID;
ObjectGuid MoiraGUID;
ObjectGuid PriestessGUID;
ObjectGuid IronhandGUID[6];
ObjectGuid CorenGUID;
ObjectGuid GoArena1GUID;
@@ -158,10 +148,68 @@ public:
uint32 TombTimer;
uint32 TombEventCounter;
uint32 OpenedCoofers;
uint32 IronhandCounter;
GuidList ArgelmachAdds;
ObjectGuid ArgelmachGUID;
TempSummon* TempSummonGrimstone = nullptr;
Position GrimstonePositon = Position(625.559f, -205.618f, -52.735f, 2.609f);
time_t timeRingFail = 0;
uint8 arenaMobsToSpawn;
uint8 arenaBossToSpawn;
std::vector<ObjectGuid> ArenaSpectators;
Position CenterOfRingOfLaw = Position(595.289, -186.56);
ObjectGuid EmperorSenators[5];
std::vector<ObjectGuid> EmperorSenatorsVector;
Position EmperorSpawnPos = Position(1380.52, -831, 115);
void OnPlayerEnter(Player* /* player */) override
{
ReplaceMoiraIfSaved(); // In case a player joins the party during the run
// SetData(TYPE_RING_OF_LAW, DONE);
}
void ReplaceMoiraIfSaved()
{
ObjectGuid* GUIDToReplace = &PriestessGUID; // default to having Moira
ObjectGuid* GUIDToSpawn = &MoiraGUID;
uint32 NPCEntry = NPC_MOIRA;
bool MoiraSaved = true;
// check if all players saved her.
Map::PlayerList const& lPlayers = instance->GetPlayers();
if (!lPlayers.isEmpty())
{
for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr)
{
if (Player* player = itr->GetSource())
{
// set to false if this player hasn't saved her. Another player can't put it to true.
MoiraSaved = MoiraSaved && ((player->GetQuestStatus(PRINCESS_QUEST_HORDE) == QUEST_STATUS_REWARDED)
|| (player->GetQuestStatus(PRINCESS_QUEST_ALLIANCE) == QUEST_STATUS_REWARDED));
}
}
}
// assign correct GUIDs and spawn targets
if (MoiraSaved)
{
GUIDToReplace = &MoiraGUID;
GUIDToSpawn = &PriestessGUID;
NPCEntry = NPC_PRIESTESS;
}
if (Creature* CreatureToReplace = instance->GetCreature(*GUIDToReplace))
{
Creature* NewSpawn = instance->SummonCreature(NPCEntry, CreatureToReplace->GetPosition());
CreatureToReplace->RemoveFromWorld();
*GUIDToSpawn = NewSpawn->GetGUID();
}
}
void Initialize() override
{
memset(&encounter, 0, sizeof(encounter));
@@ -170,8 +218,14 @@ public:
GhostKillCount = 0;
TombTimer = TIMER_TOMB_START;
TombEventCounter = 0;
OpenedCoofers = 0;
tombResetTimer = 0;
OpenedCoofers = 0;
IronhandCounter = 0;
ArenaSpectators.clear();
// these are linked to the dungeon and not how many times the arena started.
arenaMobsToSpawn = urand(0, 5);
arenaBossToSpawn = urand(0, 5);
}
void OnCreatureCreate(Creature* creature) override
@@ -214,7 +268,7 @@ public:
case NPC_MAGMUS:
MagmusGUID = creature->GetGUID();
if (!creature->IsAlive())
HandleGameObject(GetGuidData(DATA_THRONE_DOOR), true); // if Magmus is dead open door to last boss
HandleGameObject(GoThroneGUID, true); // if Magmus is dead open door to last boss
break;
case NPC_WEAPON_TECHNICIAN:
case NPC_DOOMFORGE_ARCANASMITH:
@@ -228,6 +282,38 @@ public:
case NPC_GOLEM_LORD_ARGELMACH:
ArgelmachGUID = creature->GetGUID();
break;
case NPC_IRONHAND_GUARDIAN:
IronhandGUID[IronhandCounter] = creature->GetGUID();
IronhandCounter++;
break;
case NPC_ARENA_SPECTATOR:
ArenaSpectators.push_back(creature->GetGUID());
if (encounter[TYPE_RING_OF_LAW] == DONE) // added for crashes
{
creature->SetFaction(FACTION_NEUTRAL);
creature->SetReactState(REACT_DEFENSIVE);
}
break;
case NPC_SHADOWFORGE_PEASANT:
case NPC_SHADOWFORCE_CITIZEN: // both do the same
if (creature->GetDistance2d(CenterOfRingOfLaw.GetPositionX(), CenterOfRingOfLaw.GetPositionY()) < (float)RADIUS_RING_OF_LAW)
{
ArenaSpectators.push_back(creature->GetGUID());
}
if (encounter[TYPE_RING_OF_LAW] == DONE) // added for crashes
{
creature->SetFaction(FACTION_NEUTRAL);
creature->SetReactState(REACT_DEFENSIVE);
}
break;
case NPC_SHADOWFORGE_SENATOR:
// keep track of Senators that are not too far from emperor. Can't really use emperor as creature due to him possibly not being spawned.
// some senators spawn at ring of law
if (creature->GetDistance2d(EmperorSpawnPos.GetPositionX(), EmperorSpawnPos.GetPositionY()) < (float)DISTANCE_EMPEROR_ROOM)
{
EmperorSenatorsVector.push_back(creature->GetGUID());
}
break;
default:
break;
}
@@ -309,6 +395,7 @@ public:
void OnUnitDeath(Unit* unit) override
{
uint32 deadSenators = 0;
switch (unit->GetEntry())
{
case NPC_WEAPON_TECHNICIAN:
@@ -317,6 +404,28 @@ public:
case NPC_WRATH_HAMMER_CONSTRUCT:
ArgelmachAdds.remove(unit->GetGUID());
break;
case NPC_MAGMUS:
SetData(TYPE_IRON_HALL, DONE);
break;
case NPC_SHADOWFORGE_SENATOR:
deadSenators = 1; //hacky, but we cannot count the unit that just died through its state because OnUnitDeath() is called before the state is set.
for (const auto &senatorGUID: EmperorSenatorsVector)
{
if (Creature* senator = instance->GetCreature(senatorGUID))
{
if (!senator->IsAlive() || senator->isDying())
{
deadSenators++;
}
}
}
if (Creature* emperor = instance->GetCreature(EmperorGUID))
{
// send % of senators that died
emperor->AI()->SetData(0, (100 * deadSenators) / EmperorSenatorsVector.size());
}
break;
case NPC_ANGERREL:
case NPC_DOPEREL:
case NPC_HATEREL:
@@ -343,6 +452,33 @@ public:
{
case TYPE_RING_OF_LAW:
encounter[0] = data;
switch(data)
{
case IN_PROGRESS:
TempSummonGrimstone = instance->SummonCreature(NPC_GRIMSTONE, GrimstonePositon);
break;
case FAIL:
if (TempSummonGrimstone)
{
TempSummonGrimstone->RemoveFromWorld();
TempSummonGrimstone = nullptr;
timeRingFail = time(nullptr);
}
SetData(TYPE_RING_OF_LAW, NOT_STARTED);
break;
case DONE:
for (const auto& itr : ArenaSpectators)
{
if (Creature* spectator = instance->GetCreature(itr))
{
spectator->SetFaction(FACTION_NEUTRAL);
spectator->SetReactState(REACT_DEFENSIVE);
}
}
break;
default:
break;
}
break;
case TYPE_VAULT:
encounter[1] = data;
@@ -370,9 +506,37 @@ public:
break;
case TYPE_LYCEUM:
encounter[4] = data;
if (data == DONE)
{
HandleGameObject(GetGuidData(DATA_GOLEM_DOOR_N), true);
HandleGameObject(GetGuidData(DATA_GOLEM_DOOR_S), true);
if (Creature* magmus = instance->GetCreature(MagmusGUID))
{
magmus->AI()->Talk(0);
}
ReplaceMoiraIfSaved(); // Need to place the correct final boss, but we need her to be spawned first.
}
break;
case TYPE_IRON_HALL:
encounter[5] = data;
switch (data)
{
case NOT_STARTED:
case IN_PROGRESS:
for (int i = 0; i < 6; i++)
{
if (Creature* ironhand = instance->GetCreature(IronhandGUID[i]))
{
ironhand->AI()->SetData(0, data == IN_PROGRESS);
}
}
break;
case DONE:
HandleGameObject(GetGuidData(DATA_THRONE_DOOR), true);
break;
default:
break;
}
break;
case DATA_OPEN_COFFER_DOORS:
OpenedCoofers += 1;
@@ -492,6 +656,12 @@ public:
return encounter[4];
case TYPE_IRON_HALL:
return encounter[5];
case DATA_TIME_RING_FAIL:
return timeRingFail;
case DATA_ARENA_MOBS:
return arenaMobsToSpawn;
case DATA_ARENA_BOSS:
return arenaBossToSpawn;
}
return 0;
}

View File

@@ -28,9 +28,13 @@ void AddSC_boss_draganthaurissan();
void AddSC_boss_general_angerforge();
void AddSC_boss_gorosh_the_dervish();
void AddSC_boss_grizzle();
void AddSC_boss_eviscerator();
void AddSC_boss_okthor();
void AddSC_boss_hedrum();
void AddSC_boss_high_interrogator_gerstahn();
void AddSC_boss_magmus();
void AddSC_boss_moira_bronzebeard();
void AddSC_boss_high_priestess_thaurissan();
void AddSC_boss_tomb_of_seven();
void AddSC_instance_blackrock_depths();
void AddSC_boss_drakkisath(); //Blackrock Spire
@@ -172,9 +176,13 @@ void AddEasternKingdomsScripts()
AddSC_boss_general_angerforge();
AddSC_boss_gorosh_the_dervish();
AddSC_boss_grizzle();
AddSC_boss_okthor();
AddSC_boss_eviscerator();
AddSC_boss_hedrum();
AddSC_boss_high_interrogator_gerstahn();
AddSC_boss_magmus();
AddSC_boss_moira_bronzebeard();
AddSC_boss_high_priestess_thaurissan();
AddSC_boss_tomb_of_seven();
AddSC_instance_blackrock_depths();
AddSC_boss_drakkisath(); //Blackrock Spire