Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2023-06-09 23:40:54 +08:00
18 changed files with 937 additions and 929 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ for i in `find data/sql/updates/pending* -name "*sql" -type f`; do
echo "> broadcast_text check - Failed" echo "> broadcast_text check - Failed"
echo " - DON'T EDIT broadcast_text TABLE UNLESS YOU KNOW WHAT YOU ARE DOING!" echo " - DON'T EDIT broadcast_text TABLE UNLESS YOU KNOW WHAT YOU ARE DOING!"
echo " - This error can safely be ignored if the changes are approved to be sniffed." echo " - This error can safely be ignored if the changes are approved to be sniffed."
# exit 1 exit 1
else else
echo "> broadcast_text check - OK" echo "> broadcast_text check - OK"
fi fi
@@ -0,0 +1,12 @@
-- DB update 2023_06_07_04 -> 2023_06_08_00
--
DELETE FROM `spelldifficulty_dbc` WHERE `ID` IN (8374,15039,33534,12548,33620,15659,38795);
INSERT INTO `spelldifficulty_dbc` (`ID`, `DifficultySpellID_1`, `DifficultySpellID_2`) VALUES
(8374, 8374, 38761),
(15039, 15039, 15616),
(33534, 33534, 38135),
(12548, 12548, 21401),
(33620, 33620, 38137),
(15659, 15659, 15305),
(38795, 38795, 33666);
@@ -0,0 +1,12 @@
-- DB update 2023_06_08_00 -> 2023_06_09_00
--
DELETE FROM `creature_template_movement` WHERE (`CreatureId` IN (18176,18177,18178,18179,19897,19898,19899,19900));
INSERT INTO `creature_template_movement` (`CreatureId`, `Flight`, `Rooted`) VALUES
(18176, 1, 1),
(18177, 1, 1),
(18178, 1, 1),
(18179, 1, 1),
(19897, 1, 1),
(19898, 1, 1),
(19899, 1, 1),
(19900, 1, 1);
@@ -1297,18 +1297,6 @@ AllowTickets = 1
DeletedCharacterTicketTrace = 0 DeletedCharacterTicketTrace = 0
#
# DungeonFinder.OptionsMask
# Description: Dungeon and raid finder system.
# Value is a bitmask consisting of:
# LFG_OPTION_ENABLE_DUNGEON_FINDER = 1, Enable the dungeon finder browser
# LFG_OPTION_ENABLE_RAID_BROWSER = 2, Enable the raid browser
# LFG_OPTION_ENABLE_SEASONAL_BOSSES = 4, Enable seasonal bosses
# Default: 5
DungeonFinder.OptionsMask = 5
# #
# DBC.EnforceItemAttributes # DBC.EnforceItemAttributes
# Disallow overriding item attributes stored in DBC files with values from the database # Disallow overriding item attributes stored in DBC files with values from the database
@@ -3682,6 +3670,17 @@ Calculate.Gameoject.Zone.Area.Data = 0
Group.Raid.LevelRestriction = 10 Group.Raid.LevelRestriction = 10
#
# DungeonFinder.OptionsMask
# Description: Dungeon and raid finder system.
# Value is a bitmask consisting of:
# LFG_OPTION_ENABLE_DUNGEON_FINDER = 1, Enable the dungeon finder browser
# LFG_OPTION_ENABLE_RAID_BROWSER = 2, Enable the raid browser
# LFG_OPTION_ENABLE_SEASONAL_BOSSES = 4, Enable seasonal bosses
# Default: 5
DungeonFinder.OptionsMask = 5
# #
# LFG.Location.All # LFG.Location.All
# #
@@ -5043,11 +5043,6 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
if (caster && target->CanHaveThreatList()) if (caster && target->CanHaveThreatList())
target->AddThreat(caster, 10.0f); target->AddThreat(caster, 10.0f);
break; break;
case 13139: // net-o-matic
// root to self part of (root_target->charge->root_self sequence
if (caster)
caster->CastSpell(caster, 13138, true, nullptr, this);
break;
case 34026: // kill command case 34026: // kill command
{ {
Unit* pet = target->GetGuardianPet(); Unit* pet = target->GetGuardianPet();
@@ -126,17 +126,19 @@ public:
{ {
boss_dorotheeAI(Creature* creature) : ScriptedAI(creature) boss_dorotheeAI(Creature* creature) : ScriptedAI(creature)
{ {
SetCombatMovement(false);
//this is kinda a big no-no. but it will prevent her from moving to chase targets. she should just cast her spells. in this case, since there is not really something to LOS her with or get out of range this would work. but a more elegant solution would be better
Initialize(); Initialize();
instance = creature->GetInstanceScript(); instance = creature->GetInstanceScript();
} }
void Initialize() void Initialize()
{ {
AggroTimer = 500; AggroTimer = 12000;
WaterBoltTimer = 5000; WaterBoltTimer = 0;
FearTimer = 15000; FearTimer = 15000;
SummonTitoTimer = 47500; SummonTitoTimer = 41000;
SummonedTito = false; SummonedTito = false;
TitoDied = false; TitoDied = false;
@@ -152,6 +154,7 @@ public:
bool SummonedTito; bool SummonedTito;
bool TitoDied; bool TitoDied;
bool IntroDone = false;
void Reset() override void Reset() override
{ {
@@ -160,8 +163,7 @@ public:
void JustEngagedWith(Unit* /*who*/) override void JustEngagedWith(Unit* /*who*/) override
{ {
Talk(SAY_DOROTHEE_AGGRO); me->SetInCombatWithZone();
DoZoneInCombat();
} }
void JustReachedHome() override void JustReachedHome() override
@@ -175,6 +177,7 @@ public:
{ {
Talk(SAY_DOROTHEE_DEATH); Talk(SAY_DOROTHEE_DEATH);
SummonCroneIfReady(instance, me); SummonCroneIfReady(instance, me);
me->DespawnOrUnsummon();
} }
void AttackStart(Unit* who) override void AttackStart(Unit* who) override
@@ -186,7 +189,6 @@ public:
} }
void MoveInLineOfSight(Unit* who) override void MoveInLineOfSight(Unit* who) override
{ {
if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE)) if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
return; return;
@@ -194,14 +196,35 @@ public:
ScriptedAI::MoveInLineOfSight(who); ScriptedAI::MoveInLineOfSight(who);
} }
void EnterEvadeMode(EvadeReason reason) override
{
ScriptedAI::EnterEvadeMode(reason);
if(!me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE))
{
instance->SetBossState(DATA_OPERA_PERFORMANCE, FAIL);
me->DespawnOrUnsummon();
}
}
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
if(!IntroDone)
{
if(!me->IsInEvadeMode())
{
Talk(SAY_DOROTHEE_AGGRO);
IntroDone = true;
}
}
if (AggroTimer) if (AggroTimer)
{ {
if (AggroTimer <= diff) if (AggroTimer <= diff)
{ {
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->SetImmuneToPC(false); me->SetImmuneToPC(false);
me->SetInCombatWithZone();
AggroTimer = 0; AggroTimer = 0;
} }
else else
@@ -214,7 +237,7 @@ public:
if (WaterBoltTimer <= diff) if (WaterBoltTimer <= diff)
{ {
DoCast(SelectTarget(SelectTargetMethod::Random, 0), SPELL_WATERBOLT); DoCast(SelectTarget(SelectTargetMethod::Random, 0), SPELL_WATERBOLT);
WaterBoltTimer = TitoDied ? 1500 : 5000; WaterBoltTimer = 1500;
} }
else else
WaterBoltTimer -= diff; WaterBoltTimer -= diff;
@@ -279,6 +302,7 @@ public:
Talk(SAY_DOROTHEE_TITO_DEATH, Dorothee); Talk(SAY_DOROTHEE_TITO_DEATH, Dorothee);
} }
} }
me->DespawnOrUnsummon();
} }
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
@@ -311,6 +335,136 @@ void boss_dorothee::boss_dorotheeAI::SummonTito()
} }
} }
class boss_roar : public CreatureScript
{
public:
boss_roar() : CreatureScript("boss_roar") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetKarazhanAI<boss_roarAI>(creature);
}
struct boss_roarAI : public ScriptedAI
{
boss_roarAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
uint32 AggroTimer;
uint32 MangleTimer;
uint32 ShredTimer;
uint32 ScreamTimer;
void Reset() override
{
AggroTimer = 16670;
MangleTimer = 5000;
ShredTimer = 10000;
ScreamTimer = 15000;
}
void MoveInLineOfSight(Unit* who) override
{
if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
return;
ScriptedAI::MoveInLineOfSight(who);
}
void EnterEvadeMode(EvadeReason reason) override
{
ScriptedAI::EnterEvadeMode(reason);
if(!me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE))
{
instance->SetBossState(DATA_OPERA_PERFORMANCE, FAIL);
me->DespawnOrUnsummon();
}
}
void AttackStart(Unit* who) override
{
if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
return;
ScriptedAI::AttackStart(who);
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_ROAR_AGGRO);
DoZoneInCombat();
}
void JustReachedHome() override
{
me->DespawnOrUnsummon();
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_ROAR_DEATH);
SummonCroneIfReady(instance, me);
me->DespawnOrUnsummon();
}
void KilledUnit(Unit* /*victim*/) override
{
Talk(SAY_ROAR_SLAY);
}
void UpdateAI(uint32 diff) override
{
if (AggroTimer)
{
if (AggroTimer <= diff)
{
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->SetImmuneToPC(false);
me->SetInCombatWithZone();
AggroTimer = 0;
}
else
AggroTimer -= diff;
}
if (!UpdateVictim())
return;
if (MangleTimer <= diff)
{
DoCastVictim(SPELL_MANGLE);
MangleTimer = urand(5000, 8000);
}
else
MangleTimer -= diff;
if (ShredTimer <= diff)
{
DoCastVictim(SPELL_SHRED);
ShredTimer = urand(10000, 15000);
}
else
ShredTimer -= diff;
if (ScreamTimer <= diff)
{
DoCastVictim(SPELL_FRIGHTENED_SCREAM);
ScreamTimer = urand(20000, 30000);
}
else
ScreamTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
class boss_strawman : public CreatureScript class boss_strawman : public CreatureScript
{ {
public: public:
@@ -336,7 +490,7 @@ public:
void Reset() override void Reset() override
{ {
AggroTimer = 11000; AggroTimer = 26300;
BrainBashTimer = 5000; BrainBashTimer = 5000;
BrainWipeTimer = 7000; BrainWipeTimer = 7000;
} }
@@ -350,7 +504,6 @@ public:
} }
void MoveInLineOfSight(Unit* who) override void MoveInLineOfSight(Unit* who) override
{ {
if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE)) if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
return; return;
@@ -358,6 +511,16 @@ public:
ScriptedAI::MoveInLineOfSight(who); ScriptedAI::MoveInLineOfSight(who);
} }
void EnterEvadeMode(EvadeReason reason) override
{
ScriptedAI::EnterEvadeMode(reason);
if(!me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE))
{
instance->SetBossState(DATA_OPERA_PERFORMANCE, FAIL);
me->DespawnOrUnsummon();
}
}
void JustEngagedWith(Unit* /*who*/) override void JustEngagedWith(Unit* /*who*/) override
{ {
Talk(SAY_STRAWMAN_AGGRO); Talk(SAY_STRAWMAN_AGGRO);
@@ -385,8 +548,8 @@ public:
void JustDied(Unit* /*killer*/) override void JustDied(Unit* /*killer*/) override
{ {
Talk(SAY_STRAWMAN_DEATH); Talk(SAY_STRAWMAN_DEATH);
SummonCroneIfReady(instance, me); SummonCroneIfReady(instance, me);
me->DespawnOrUnsummon();
} }
void KilledUnit(Unit* /*victim*/) override void KilledUnit(Unit* /*victim*/) override
@@ -402,6 +565,7 @@ public:
{ {
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->SetImmuneToPC(false); me->SetImmuneToPC(false);
me->SetInCombatWithZone();
AggroTimer = 0; AggroTimer = 0;
} }
else else
@@ -460,7 +624,7 @@ public:
void Reset() override void Reset() override
{ {
AggroTimer = 15000; AggroTimer = 34470;
CleaveTimer = 5000; CleaveTimer = 5000;
RustTimer = 15000; RustTimer = 15000;
@@ -487,7 +651,6 @@ public:
} }
void MoveInLineOfSight(Unit* who) override void MoveInLineOfSight(Unit* who) override
{ {
if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE)) if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
return; return;
@@ -495,11 +658,22 @@ public:
ScriptedAI::MoveInLineOfSight(who); ScriptedAI::MoveInLineOfSight(who);
} }
void EnterEvadeMode(EvadeReason reason) override
{
ScriptedAI::EnterEvadeMode(reason);
if(!me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE))
{
instance->SetBossState(DATA_OPERA_PERFORMANCE, FAIL);
me->DespawnOrUnsummon();
}
}
void JustDied(Unit* /*killer*/) override void JustDied(Unit* /*killer*/) override
{ {
Talk(SAY_TINHEAD_DEATH); Talk(SAY_TINHEAD_DEATH);
SummonCroneIfReady(instance, me); SummonCroneIfReady(instance, me);
me->DespawnOrUnsummon();
} }
void KilledUnit(Unit* /*victim*/) override void KilledUnit(Unit* /*victim*/) override
@@ -515,6 +689,7 @@ public:
{ {
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->SetImmuneToPC(false); me->SetImmuneToPC(false);
me->SetInCombatWithZone();
AggroTimer = 0; AggroTimer = 0;
} }
else else
@@ -550,124 +725,6 @@ public:
}; };
}; };
class boss_roar : public CreatureScript
{
public:
boss_roar() : CreatureScript("boss_roar") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetKarazhanAI<boss_roarAI>(creature);
}
struct boss_roarAI : public ScriptedAI
{
boss_roarAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
uint32 AggroTimer;
uint32 MangleTimer;
uint32 ShredTimer;
uint32 ScreamTimer;
void Reset() override
{
AggroTimer = 20000;
MangleTimer = 5000;
ShredTimer = 10000;
ScreamTimer = 15000;
}
void MoveInLineOfSight(Unit* who) override
{
if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
return;
ScriptedAI::MoveInLineOfSight(who);
}
void AttackStart(Unit* who) override
{
if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
return;
ScriptedAI::AttackStart(who);
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_ROAR_AGGRO);
DoZoneInCombat();
}
void JustReachedHome() override
{
me->DespawnOrUnsummon();
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_ROAR_DEATH);
SummonCroneIfReady(instance, me);
}
void KilledUnit(Unit* /*victim*/) override
{
Talk(SAY_ROAR_SLAY);
}
void UpdateAI(uint32 diff) override
{
if (AggroTimer)
{
if (AggroTimer <= diff)
{
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->SetImmuneToPC(false);
AggroTimer = 0;
}
else
AggroTimer -= diff;
}
if (!UpdateVictim())
return;
if (MangleTimer <= diff)
{
DoCastVictim(SPELL_MANGLE);
MangleTimer = urand(5000, 8000);
}
else
MangleTimer -= diff;
if (ShredTimer <= diff)
{
DoCastVictim(SPELL_SHRED);
ShredTimer = urand(10000, 15000);
}
else
ShredTimer -= diff;
if (ScreamTimer <= diff)
{
DoCastVictim(SPELL_FRIGHTENED_SCREAM);
ScreamTimer = urand(20000, 30000);
}
else
ScreamTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
class boss_crone : public CreatureScript class boss_crone : public CreatureScript
{ {
public: public:
@@ -38,4 +38,6 @@ inline AI* GetAuchenaiCryptsAI(T* obj)
return GetInstanceAI<AI>(obj, ACScriptName); return GetInstanceAI<AI>(obj, ACScriptName);
} }
#define RegisterAuchenaiCryptsCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetAuchenaiCryptsAI)
#endif // AUCHENAI_CRYPTS_H_ #endif // AUCHENAI_CRYPTS_H_
@@ -19,142 +19,26 @@
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "auchenai_crypts.h" #include "auchenai_crypts.h"
enum ExarchMaladaar enum Text
{ {
SAY_INTRO = 0, SAY_INTRO = 0,
SAY_SUMMON = 1, SAY_SUMMON = 1,
SAY_AGGRO = 2, SAY_AGGRO = 2,
SAY_ROAR = 3, SAY_ROAR = 3,
SAY_SLAY = 4, SAY_SLAY = 4,
SAY_DEATH = 5, SAY_DEATH = 5
};
enum Spells
{
// Exarch Maladaar
SPELL_RIBBON_OF_SOULS = 32422, SPELL_RIBBON_OF_SOULS = 32422,
SPELL_SOUL_SCREAM = 32421, SPELL_SOUL_SCREAM = 32421,
SPELL_STOLEN_SOUL = 32346, SPELL_STOLEN_SOUL = 32346,
SPELL_STOLEN_SOUL_VISUAL = 32395, SPELL_STOLEN_SOUL_VISUAL = 32395,
SPELL_SUMMON_AVATAR = 32424, SPELL_SUMMON_AVATAR = 32424,
ENTRY_STOLEN_SOUL = 18441, // Stolen Soul
EVENT_SPELL_FEAR = 1,
EVENT_SPELL_RIBBON = 2,
EVENT_SPELL_SOUL = 3,
EVENT_CHECK_HEALTH = 4
};
class boss_exarch_maladaar : public CreatureScript
{
public:
boss_exarch_maladaar() : CreatureScript("boss_exarch_maladaar") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetAuchenaiCryptsAI<boss_exarch_maladaarAI>(creature);
}
struct boss_exarch_maladaarAI : public ScriptedAI
{
boss_exarch_maladaarAI(Creature* creature) : ScriptedAI(creature)
{
_talked = false;
}
bool _talked;
EventMap events;
void Reset() override
{
events.Reset();
}
void MoveInLineOfSight(Unit* who) override
{
if (!_talked && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 150.0f))
{
Talk(SAY_INTRO);
_talked = true;
}
ScriptedAI::MoveInLineOfSight(who);
}
void JustEngagedWith(Unit*) override
{
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_SPELL_FEAR, 15000);
events.ScheduleEvent(EVENT_SPELL_RIBBON, 5000);
events.ScheduleEvent(EVENT_SPELL_SOUL, 25000);
events.ScheduleEvent(EVENT_CHECK_HEALTH, 5000);
}
void KilledUnit(Unit*) override
{
if (urand(0, 1))
Talk(SAY_SLAY);
}
void JustDied(Unit*) override
{
Talk(SAY_DEATH);
//When Exarch Maladar is defeated D'ore appear.
me->SummonCreature(19412, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 600000);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_CHECK_HEALTH:
if (HealthBelowPct(25))
{
Talk(SAY_SUMMON);
me->CastSpell(me, SPELL_SUMMON_AVATAR, false);
return;
}
events.RepeatEvent(2000);
break;
case EVENT_SPELL_SOUL:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
{
Talk(SAY_ROAR);
me->CastSpell(target, SPELL_STOLEN_SOUL, false);
if (Creature* summon = me->SummonCreature(ENTRY_STOLEN_SOUL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000))
{
summon->CastSpell(summon, SPELL_STOLEN_SOUL_VISUAL, false);
summon->SetDisplayId(target->GetDisplayId());
summon->AI()->DoAction(target->getClass());
summon->AI()->AttackStart(target);
}
}
events.RepeatEvent(urand(25000, 30000));
break;
case EVENT_SPELL_RIBBON:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
me->CastSpell(target, SPELL_RIBBON_OF_SOULS, false);
events.RepeatEvent(urand(10000, 20000));
break;
case EVENT_SPELL_FEAR:
me->CastSpell(me, SPELL_SOUL_SCREAM, false);
events.RepeatEvent(urand(15000, 25000));
break;
}
DoMeleeAttackIfReady();
}
};
};
enum stolenSoul
{
SPELL_MOONFIRE = 37328, SPELL_MOONFIRE = 37328,
SPELL_FIREBALL = 37329, SPELL_FIREBALL = 37329,
SPELL_MIND_FLAY = 37330, SPELL_MIND_FLAY = 37330,
@@ -164,32 +48,189 @@ enum stolenSoul
SPELL_MORTAL_STRIKE = 37335, SPELL_MORTAL_STRIKE = 37335,
SPELL_FREEZING_TRAP = 37368, SPELL_FREEZING_TRAP = 37368,
SPELL_HAMMER_OF_JUSTICE = 37369, SPELL_HAMMER_OF_JUSTICE = 37369,
SPELL_PLAGUE_STRIKE = 58839, SPELL_PLAGUE_STRIKE = 58839
EVENT_STOLEN_SOUL_SPELL = 1,
}; };
class npc_stolen_soul : public CreatureScript enum Npc
{ {
public: ENTRY_STOLEN_SOUL = 18441
npc_stolen_soul() : CreatureScript("npc_stolen_soul") { } };
CreatureAI* GetAI(Creature* creature) const override struct boss_exarch_maladaar : public BossAI
{ {
return GetAuchenaiCryptsAI<npc_stolen_soulAI>(creature); boss_exarch_maladaar(Creature* creature) : BossAI(creature, DATA_EXARCH_MALADAAR)
{
_talked = false;
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
} }
struct npc_stolen_soulAI : public ScriptedAI bool _talked;
void Reset() override
{ {
npc_stolen_soulAI(Creature* creature) : ScriptedAI(creature) {} _Reset();
ScheduleHealthCheckEvent(25, [&] {
Talk(SAY_SUMMON);
DoCastSelf(SPELL_SUMMON_AVATAR);
});
}
void MoveInLineOfSight(Unit* who) override
{
if (!_talked && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 150.0f))
{
_talked = true;
Talk(SAY_INTRO);
}
ScriptedAI::MoveInLineOfSight(who);
}
void JustEngagedWith(Unit*) override
{
_JustEngagedWith();
Talk(SAY_AGGRO);
scheduler.Schedule(15s, [this] (TaskContext context)
{
DoCastSelf(SPELL_SOUL_SCREAM);
context.Repeat(15s, 25s);
}).Schedule(5s, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_RIBBON_OF_SOULS);
context.Repeat(10s, 20s);
}).Schedule(25s, [this](TaskContext context)
{
if (Unit * target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
{
Talk(SAY_ROAR);
DoCast(target, SPELL_STOLEN_SOUL);
if (Creature* summon = me->SummonCreature(ENTRY_STOLEN_SOUL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000))
{
summon->CastSpell(summon, SPELL_STOLEN_SOUL_VISUAL, false);
summon->SetDisplayId(target->GetDisplayId());
summon->AI()->DoAction(target->getClass());
summon->AI()->AttackStart(target);
}
}
context.Repeat(25s, 30s);
});
}
void KilledUnit(Unit* victim) override
{
if (victim->IsPlayer() && urand(0, 1))
{
Talk(SAY_SLAY);
}
}
void JustDied(Unit*) override
{
Talk(SAY_DEATH);
me->SummonCreature(19412, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 600000);
_JustDied();
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoMeleeAttackIfReady();
}
};
struct npc_stolen_soul : public ScriptedAI
{
npc_stolen_soul(Creature* creature) : ScriptedAI(creature) {}
uint8 myClass; uint8 myClass;
EventMap events;
void Reset() override void Reset() override
{ {
myClass = CLASS_WARRIOR; myClass = CLASS_WARRIOR;
events.ScheduleEvent(EVENT_STOLEN_SOUL_SPELL, 1000); _scheduler.Schedule(1s, [this] (TaskContext /*context*/)
{
switch (myClass)
{
case CLASS_WARRIOR:
_scheduler.Schedule(0ms, [this](TaskContext context)
{
DoCastVictim(SPELL_MORTAL_STRIKE);
context.Repeat(6s);
});
break;
case CLASS_PALADIN:
_scheduler.Schedule(0ms, [this](TaskContext context)
{
DoCastVictim(SPELL_HAMMER_OF_JUSTICE);
context.Repeat(6s);
});
break;
case CLASS_HUNTER:
_scheduler.Schedule(0ms, [this](TaskContext context)
{
DoCastVictim(SPELL_FREEZING_TRAP);
context.Repeat(20s);
});
break;
case CLASS_ROGUE:
_scheduler.Schedule(0ms, [this](TaskContext context)
{
DoCastVictim(SPELL_HEMORRHAGE);
context.Repeat(10s);
});
break;
case CLASS_PRIEST:
_scheduler.Schedule(0ms, [this](TaskContext context)
{
DoCastVictim(SPELL_MIND_FLAY);
context.Repeat(5s);
});
break;
case CLASS_SHAMAN:
_scheduler.Schedule(0ms, [this](TaskContext context)
{
DoCastVictim(SPELL_FROSTSHOCK);
context.Repeat(8s);
});
break;
case CLASS_MAGE:
_scheduler.Schedule(0ms, [this](TaskContext context)
{
DoCastVictim(SPELL_FIREBALL);
context.Repeat(5s);
});
break;
case CLASS_WARLOCK:
_scheduler.Schedule(0ms, [this](TaskContext context)
{
DoCastVictim(SPELL_CURSE_OF_AGONY);
context.Repeat(20s);
});
break;
case CLASS_DRUID:
_scheduler.Schedule(0ms, [this](TaskContext context)
{
DoCastVictim(SPELL_MOONFIRE);
context.Repeat(10s);
});
break;
case CLASS_DEATH_KNIGHT:
_scheduler.Schedule(0ms, [this](TaskContext context)
{
DoCastVictim(SPELL_PLAGUE_STRIKE);
context.Repeat(6s);
});
break;
}
});
} }
void DoAction(int32 pClass) override void DoAction(int32 pClass) override
@@ -202,61 +243,16 @@ public:
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
events.Update(diff); _scheduler.Update(diff);
if (events.ExecuteEvent() == EVENT_STOLEN_SOUL_SPELL)
{
switch (myClass)
{
case CLASS_WARRIOR:
me->CastSpell(me->GetVictim(), SPELL_MORTAL_STRIKE, false);
events.RepeatEvent(6000);
break;
case CLASS_PALADIN:
me->CastSpell(me->GetVictim(), SPELL_HAMMER_OF_JUSTICE, false);
events.RepeatEvent(6000);
break;
case CLASS_HUNTER:
me->CastSpell(me->GetVictim(), SPELL_FREEZING_TRAP, false);
events.RepeatEvent(20000);
break;
case CLASS_ROGUE:
me->CastSpell(me->GetVictim(), SPELL_HEMORRHAGE, false);
events.RepeatEvent(10000);
break;
case CLASS_PRIEST:
me->CastSpell(me->GetVictim(), SPELL_MIND_FLAY, false);
events.RepeatEvent(5000);
break;
case CLASS_SHAMAN:
me->CastSpell(me->GetVictim(), SPELL_FROSTSHOCK, false);
events.RepeatEvent(8000);
break;
case CLASS_MAGE:
me->CastSpell(me->GetVictim(), SPELL_FIREBALL, false);
events.RepeatEvent(5000);
break;
case CLASS_WARLOCK:
me->CastSpell(me->GetVictim(), SPELL_CURSE_OF_AGONY, false);
events.RepeatEvent(20000);
break;
case CLASS_DRUID:
me->CastSpell(me->GetVictim(), SPELL_MOONFIRE, false);
events.RepeatEvent(10000);
break;
case CLASS_DEATH_KNIGHT:
me->CastSpell(me->GetVictim(), SPELL_PLAGUE_STRIKE, false);
events.RepeatEvent(6000);
break;
}
}
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
};
private:
TaskScheduler _scheduler;
}; };
void AddSC_boss_exarch_maladaar() void AddSC_boss_exarch_maladaar()
{ {
new boss_exarch_maladaar(); RegisterAuchenaiCryptsCreatureAI(boss_exarch_maladaar);
new npc_stolen_soul(); RegisterAuchenaiCryptsCreatureAI(npc_stolen_soul);
} }
@@ -22,68 +22,133 @@
#include "SpellScript.h" #include "SpellScript.h"
#include "auchenai_crypts.h" #include "auchenai_crypts.h"
enum eShirrak enum Spells
{ {
SPELL_INHIBIT_MAGIC = 32264, SPELL_INHIBIT_MAGIC = 32264,
SPELL_ATTRACT_MAGIC = 32265, SPELL_ATTRACT_MAGIC = 32265,
SPELL_CARNIVOROUS_BITE_N = 36383, SPELL_CARNIVOROUS_BITE = 36383,
SPELL_CARNIVOROUS_BITE_H = 39382, SPELL_FIERY_BLAST = 32302,
SPELL_FIERY_BLAST_N = 32302,
SPELL_FIERY_BLAST_H = 38382,
SPELL_FOCUS_FIRE_VISUAL = 32286, SPELL_FOCUS_FIRE_VISUAL = 32286,
SPELL_FOCUS_CAST = 32300, SPELL_FOCUS_CAST = 32300,
EVENT_SPELL_INHIBIT_MAGIC = 1, SPELL_POSSESS_INSTANT = 32830,
EVENT_SPELL_ATTRACT_MAGIC = 2, SPELL_POSSESS_CHANNELED = 33401
EVENT_SPELL_CARNIVOROUS = 3, };
EVENT_SPELL_FOCUS_FIRE = 4,
EVENT_SPELL_FOCUS_FIRE_2 = 5,
EVENT_SPELL_FOCUS_FIRE_3 = 6,
enum Misc
{
ENTRY_FOCUS_FIRE = 18374, ENTRY_FOCUS_FIRE = 18374,
EMOTE_FOCUSED = 0 EMOTE_FOCUSED = 0
}; };
class boss_shirrak_the_dead_watcher : public CreatureScript struct boss_shirrak_the_dead_watcher : public BossAI
{ {
public: boss_shirrak_the_dead_watcher(Creature* creature) : BossAI(creature, DATA_SHIRRAK_THE_DEAD_WATCHER)
boss_shirrak_the_dead_watcher() : CreatureScript("boss_shirrak_the_dead_watcher") { }
CreatureAI* GetAI(Creature* creature) const override
{ {
return GetAuchenaiCryptsAI<boss_shirrak_the_dead_watcherAI>(creature); scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
} }
struct boss_shirrak_the_dead_watcherAI : public ScriptedAI
{
boss_shirrak_the_dead_watcherAI(Creature* creature) : ScriptedAI(creature)
{
}
EventMap events;
ObjectGuid focusGUID; ObjectGuid focusGUID;
void EnterEvadeMode(EvadeReason why) override void EnterEvadeMode(EvadeReason why) override
{ {
me->SetControlled(false, UNIT_STATE_ROOT); me->SetControlled(false, UNIT_STATE_ROOT);
ScriptedAI::EnterEvadeMode(why); CreatureAI::EnterEvadeMode(why);
} }
void Reset() override void Reset() override
{ {
events.Reset(); _Reset();
focusGUID.Clear(); focusGUID.Clear();
me->SetControlled(false, UNIT_STATE_ROOT); me->SetControlled(false, UNIT_STATE_ROOT);
} }
void JustEngagedWith(Unit*) override void JustEngagedWith(Unit*) override
{ {
events.ScheduleEvent(EVENT_SPELL_INHIBIT_MAGIC, 0); _JustEngagedWith();
events.ScheduleEvent(EVENT_SPELL_ATTRACT_MAGIC, 28000); scheduler.Schedule(1ms, [this] (TaskContext context)
events.ScheduleEvent(EVENT_SPELL_CARNIVOROUS, 10000); {
events.ScheduleEvent(EVENT_SPELL_FOCUS_FIRE, 17000); Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers();
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if (Player* player = i->GetSource())
{
float dist = me->GetDistance(player);
if (player->IsAlive() && dist < 45.0f)
{
Aura* aura = player->GetAura(SPELL_INHIBIT_MAGIC);
if (!aura)
{
aura = me->AddAura(SPELL_INHIBIT_MAGIC, player);
}
else
{
aura->RefreshDuration();
}
if (aura)
{
aura->SetStackAmount(getStackCount(dist));
}
}
else
{
player->RemoveAurasDueToSpell(SPELL_INHIBIT_MAGIC);
}
}
}
context.Repeat(3s);
}).Schedule(28s, [this](TaskContext context)
{
DoCastSelf(SPELL_ATTRACT_MAGIC);
context.Repeat(30s);
scheduler.Schedule(1500ms, [this](TaskContext context)
{
DoCastSelf(SPELL_CARNIVOROUS_BITE);
context.Repeat(10s);
});
}).Schedule(10s, [this](TaskContext context)
{
DoCastSelf(SPELL_CARNIVOROUS_BITE);
context.Repeat(10s);
}).Schedule(17s, [this](TaskContext context)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
{
if (Creature* cr = me->SummonCreature(ENTRY_FOCUS_FIRE, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 7000))
{
focusGUID = cr->GetGUID();
}
Talk(EMOTE_FOCUSED, target);
}
context.Repeat(15s, 20s);
scheduler.Schedule(3s, [this](TaskContext /*context*/)
{
if (Unit* flare = ObjectAccessor::GetCreature(*me, focusGUID))
{
me->CastSpell(flare, SPELL_FOCUS_CAST, true);
}
}).Schedule(3500ms, [this](TaskContext /*context*/)
{
if (Unit* flare = ObjectAccessor::GetCreature(*me, focusGUID))
{
me->CastSpell(flare, SPELL_FOCUS_CAST, true);
}
}).Schedule(4s, [this](TaskContext /*context*/)
{
if (Unit* flare = ObjectAccessor::GetCreature(*me, focusGUID))
{
me->CastSpell(flare, SPELL_FOCUS_CAST, true);
}
}).Schedule(5s, [this](TaskContext /*context*/)
{
me->SetControlled(false, UNIT_STATE_ROOT);
});
me->SetControlled(true, UNIT_STATE_ROOT);
});
} }
void JustSummoned(Creature* summon) override void JustSummoned(Creature* summon) override
@@ -94,7 +159,9 @@ public:
void SpellHitTarget(Unit* target, SpellInfo const* spellInfo) override void SpellHitTarget(Unit* target, SpellInfo const* spellInfo) override
{ {
if (spellInfo->Id == SPELL_FOCUS_CAST) if (spellInfo->Id == SPELL_FOCUS_CAST)
target->CastSpell(target, DUNGEON_MODE(SPELL_FIERY_BLAST_N, SPELL_FIERY_BLAST_H), false); {
target->CastSpell(target, SPELL_FIERY_BLAST, false);
}
} }
uint8 getStackCount(float dist) uint8 getStackCount(float dist)
@@ -110,84 +177,17 @@ public:
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
events.Update(diff); scheduler.Update(diff);
uint32 eventId = events.ExecuteEvent();
if (eventId == EVENT_SPELL_INHIBIT_MAGIC)
{
Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers();
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
if (Player* player = i->GetSource())
{
float dist = me->GetDistance(player);
if (player->IsAlive() && dist < 45.0f)
{
Aura* aura = player->GetAura(SPELL_INHIBIT_MAGIC);
if (!aura)
aura = me->AddAura(SPELL_INHIBIT_MAGIC, player);
else
aura->RefreshDuration();
if (aura)
aura->SetStackAmount(getStackCount(dist));
}
else
player->RemoveAurasDueToSpell(SPELL_INHIBIT_MAGIC);
}
events.RepeatEvent(3000);
return;
}
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
switch (eventId)
{
case EVENT_SPELL_ATTRACT_MAGIC:
me->CastSpell(me, SPELL_ATTRACT_MAGIC, false);
events.RepeatEvent(30000);
events.RescheduleEvent(EVENT_SPELL_CARNIVOROUS, 1500);
break;
case EVENT_SPELL_CARNIVOROUS:
me->CastSpell(me, DUNGEON_MODE(SPELL_CARNIVOROUS_BITE_N, SPELL_CARNIVOROUS_BITE_H), false);
events.RepeatEvent(10000);
break;
case EVENT_SPELL_FOCUS_FIRE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
{
if (Creature* cr = me->SummonCreature(ENTRY_FOCUS_FIRE, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 7000))
focusGUID = cr->GetGUID();
Talk(EMOTE_FOCUSED, target);
}
events.RepeatEvent(urand(15000, 20000));
events.ScheduleEvent(EVENT_SPELL_FOCUS_FIRE_2, 3000);
events.ScheduleEvent(EVENT_SPELL_FOCUS_FIRE_2, 3500);
events.ScheduleEvent(EVENT_SPELL_FOCUS_FIRE_2, 4000);
events.ScheduleEvent(EVENT_SPELL_FOCUS_FIRE_3, 5000);
me->SetControlled(true, UNIT_STATE_ROOT);
break;
case EVENT_SPELL_FOCUS_FIRE_2:
if (Unit* flare = ObjectAccessor::GetCreature(*me, focusGUID))
me->CastSpell(flare, SPELL_FOCUS_CAST, true);
break;
case EVENT_SPELL_FOCUS_FIRE_3:
me->SetControlled(false, UNIT_STATE_ROOT);
break;
}
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
};
class spell_auchenai_possess : public SpellScriptLoader class spell_auchenai_possess : public AuraScript
{ {
public: PrepareAuraScript(spell_auchenai_possess);
spell_auchenai_possess() : SpellScriptLoader("spell_auchenai_possess") { }
class spell_auchenai_possess_AuraScript : public AuraScript
{
PrepareAuraScript(spell_auchenai_possess_AuraScript);
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{ {
@@ -197,8 +197,12 @@ public:
} }
if (Unit* caster = GetCaster()) if (Unit* caster = GetCaster())
{
if (Unit* target = GetTarget()) if (Unit* target = GetTarget())
caster->CastSpell(target, 32830 /*POSSESS*/, true); {
caster->CastSpell(target, SPELL_POSSESS_INSTANT, true);
}
}
} }
void CalcPeriodic(AuraEffect const* /*effect*/, bool& isPeriodic, int32& amplitude) void CalcPeriodic(AuraEffect const* /*effect*/, bool& isPeriodic, int32& amplitude)
@@ -209,33 +213,31 @@ public:
void Update(AuraEffect* /*effect*/) void Update(AuraEffect* /*effect*/)
{ {
// Xinef: Charm is removed when target is at or below 50%hp
if (Unit* owner = GetUnitOwner()) if (Unit* owner = GetUnitOwner())
{
if (owner->GetHealthPct() <= 50) if (owner->GetHealthPct() <= 50)
{
SetDuration(0); SetDuration(0);
} }
}
}
void Register() override void Register() override
{ {
// Base channel if (m_scriptSpellId == SPELL_POSSESS_CHANNELED)
if (m_scriptSpellId == 33401) {
OnEffectRemove += AuraEffectRemoveFn(spell_auchenai_possess_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); OnEffectRemove += AuraEffectRemoveFn(spell_auchenai_possess::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
}
else else
{ {
DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_auchenai_possess_AuraScript::CalcPeriodic, EFFECT_0, SPELL_AURA_MOD_CHARM); DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_auchenai_possess::CalcPeriodic, EFFECT_0, SPELL_AURA_MOD_CHARM);
OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_auchenai_possess_AuraScript::Update, EFFECT_0, SPELL_AURA_MOD_CHARM); OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_auchenai_possess::Update, EFFECT_0, SPELL_AURA_MOD_CHARM);
} }
} }
}; };
AuraScript* GetAuraScript() const override
{
return new spell_auchenai_possess_AuraScript();
}
};
void AddSC_boss_shirrak_the_dead_watcher() void AddSC_boss_shirrak_the_dead_watcher()
{ {
new boss_shirrak_the_dead_watcher(); RegisterAuchenaiCryptsCreatureAI(boss_shirrak_the_dead_watcher);
new spell_auchenai_possess(); RegisterSpellScript(spell_auchenai_possess);
} }
@@ -20,60 +20,56 @@
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "mana_tombs.h" #include "mana_tombs.h"
enum ePrince enum Text
{ {
SAY_INTRO = 0, SAY_INTRO = 0,
SAY_AGGRO = 1, SAY_AGGRO = 1,
SAY_SLAY = 2, SAY_SLAY = 2,
SAY_SUMMON = 3, SAY_SUMMON = 3,
SAY_DEAD = 4, SAY_DEAD = 4
};
enum Spells
{
// Shaffar
SPELL_BLINK = 34605, SPELL_BLINK = 34605,
SPELL_FROSTBOLT = 32364, SPELL_FROSTBOLT = 32364,
SPELL_FIREBALL = 32363, SPELL_FIREBALL = 32363,
SPELL_FROSTNOVA = 32365, SPELL_FROSTNOVA = 32365,
SPELL_ETHEREAL_BEACON = 32371, // Summons NPC_BEACON SPELL_ETHEREAL_BEACON = 32371, // Summons NPC_BEACON
SPELL_ETHEREAL_BEACON_VISUAL = 32368, SPELL_ETHEREAL_BEACON_VISUAL = 32368,
NPC_BEACON = 18431, // Yor
NPC_SHAFFAR = 18344, SPELL_DOUBLE_BREATH = 38361,
SPELL_STOMP = 36405
EVENT_SPELL_BEACON = 1,
EVENT_SPELL_FR_FI = 2,
EVENT_SPELL_FROST_NOVA = 3,
EVENT_SPELL_BLINK = 4,
}; };
class boss_nexusprince_shaffar : public CreatureScript enum Npc
{ {
public: NPC_BEACON = 18431
boss_nexusprince_shaffar() : CreatureScript("boss_nexusprince_shaffar") { } };
CreatureAI* GetAI(Creature* creature) const override struct boss_nexusprince_shaffar : public BossAI
{ {
return GetManaTombsAI<boss_nexusprince_shaffarAI>(creature); boss_nexusprince_shaffar(Creature* creature) : BossAI(creature, DATA_NEXUSPRINCE_SHAFFAR), summons(me)
}
struct boss_nexusprince_shaffarAI : public ScriptedAI
{
boss_nexusprince_shaffarAI(Creature* creature) : ScriptedAI(creature), summons(me)
{ {
HasTaunted = false; HasTaunted = false;
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
} }
EventMap events;
SummonList summons; SummonList summons;
bool HasTaunted; bool HasTaunted;
void Reset() override void Reset() override
{ {
_Reset();
float dist = 8.0f; float dist = 8.0f;
float posX, posY, posZ, angle; float posX, posY, posZ, angle;
me->GetHomePosition(posX, posY, posZ, angle); me->GetHomePosition(posX, posY, posZ, angle);
summons.DespawnAll(); summons.DespawnAll();
events.Reset();
me->SummonCreature(NPC_BEACON, posX - dist, posY - dist, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); me->SummonCreature(NPC_BEACON, posX - dist, posY - dist, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000);
me->SummonCreature(NPC_BEACON, posX - dist, posY + dist, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); me->SummonCreature(NPC_BEACON, posX - dist, posY + dist, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000);
me->SummonCreature(NPC_BEACON, posX + dist, posY, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); me->SummonCreature(NPC_BEACON, posX + dist, posY, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000);
@@ -83,21 +79,38 @@ public:
{ {
if (!HasTaunted && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 100.0f)) if (!HasTaunted && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 100.0f))
{ {
Talk(SAY_INTRO);
HasTaunted = true; HasTaunted = true;
Talk(SAY_INTRO);
} }
} }
void JustEngagedWith(Unit*) override void JustEngagedWith(Unit*) override
{ {
_JustEngagedWith();
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
me->SetInCombatWithZone();
summons.DoZoneInCombat(); summons.DoZoneInCombat();
scheduler.Schedule(10s, [this](TaskContext context)
events.ScheduleEvent(EVENT_SPELL_BEACON, 10000); {
events.ScheduleEvent(EVENT_SPELL_FR_FI, 4000); if (!urand(0, 3))
events.ScheduleEvent(EVENT_SPELL_FROST_NOVA, 15000); {
Talk(SAY_SUMMON);
}
DoCastSelf(SPELL_ETHEREAL_BEACON, true);
context.Repeat(10s);
}).Schedule(4s, [this](TaskContext context)
{
DoCastVictim(RAND(SPELL_FROSTBOLT, SPELL_FIREBALL));
context.Repeat(3s, 4s);
}).Schedule(15s, [this](TaskContext context)
{
DoCastSelf(SPELL_FROSTNOVA);
context.Repeat(16s, 23s);
scheduler.DelayAll(1500ms);
scheduler.Schedule(1500ms, [this](TaskContext /*context*/)
{
DoCastSelf(SPELL_BLINK);
});
});
} }
void JustSummoned(Creature* summon) override void JustSummoned(Creature* summon) override
@@ -106,9 +119,10 @@ public:
{ {
summon->CastSpell(summon, SPELL_ETHEREAL_BEACON_VISUAL, false); summon->CastSpell(summon, SPELL_ETHEREAL_BEACON_VISUAL, false);
if (Unit* target = SelectTargetFromPlayerList(50.0f)) if (Unit* target = SelectTargetFromPlayerList(50.0f))
{
summon->AI()->AttackStart(target); summon->AI()->AttackStart(target);
} }
}
summons.Summon(summon); summons.Summon(summon);
} }
@@ -120,11 +134,14 @@ public:
void KilledUnit(Unit* victim) override void KilledUnit(Unit* victim) override
{ {
if (victim->GetTypeId() == TYPEID_PLAYER) if (victim->GetTypeId() == TYPEID_PLAYER)
{
Talk(SAY_SLAY); Talk(SAY_SLAY);
} }
}
void JustDied(Unit* /*killer*/) override void JustDied(Unit* /*killer*/) override
{ {
_JustDied();
Talk(SAY_DEAD); Talk(SAY_DEAD);
summons.DespawnAll(); summons.DespawnAll();
} }
@@ -134,69 +151,34 @@ public:
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
events.Update(diff); scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING)) if (me->HasUnitState(UNIT_STATE_CASTING))
return; return;
switch (events.ExecuteEvent())
{
case EVENT_SPELL_FROST_NOVA:
me->CastSpell(me, SPELL_FROSTNOVA, false);
events.RepeatEvent(urand(16000, 23000));
events.DelayEvents(1500);
events.ScheduleEvent(EVENT_SPELL_BLINK, 1500);
break;
case EVENT_SPELL_FR_FI:
me->CastSpell(me->GetVictim(), RAND(SPELL_FROSTBOLT, SPELL_FIREBALL), false);
events.RepeatEvent(urand(3000, 4000));
break;
case EVENT_SPELL_BLINK:
me->CastSpell(me, SPELL_BLINK, false);
events.RescheduleEvent(EVENT_SPELL_FR_FI, 0);
break;
case EVENT_SPELL_BEACON:
if (!urand(0, 3))
Talk(SAY_SUMMON);
me->CastSpell(me, SPELL_ETHEREAL_BEACON, true);
events.RepeatEvent(10000);
break;
}
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
};
enum Yor struct npc_yor : public ScriptedAI
{ {
SPELL_DOUBLE_BREATH = 38361, npc_yor(Creature* creature) : ScriptedAI(creature) { }
SPELL_STOMP = 36405,
EVENT_DOUBLE_BREATH = 1,
EVENT_STOMP = 2
};
class npc_yor : public CreatureScript
{
public:
npc_yor() : CreatureScript("npc_yor") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetManaTombsAI<npc_yorAI>(creature);
}
struct npc_yorAI : public ScriptedAI
{
npc_yorAI(Creature* creature) : ScriptedAI(creature) { }
void Reset() override { } void Reset() override { }
void JustEngagedWith(Unit* /*who*/) override void JustEngagedWith(Unit* /*who*/) override
{ {
events.ScheduleEvent(EVENT_DOUBLE_BREATH, urand(26500, 30500)); _scheduler.Schedule(25500ms, 30500ms, [this](TaskContext context)
events.ScheduleEvent(EVENT_STOMP, urand(12000, 18000)); {
if (me->IsWithinDist(me->GetVictim(), ATTACK_DISTANCE))
{
DoCastVictim(SPELL_DOUBLE_BREATH);
}
context.Repeat(10s, 20s);
}).Schedule(12s, 18s, [this](TaskContext context)
{
DoCastAOE(SPELL_STOMP);
context.Repeat(14s, 24s);
});
} }
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
@@ -204,36 +186,19 @@ public:
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
events.Update(diff); _scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING)) if (me->HasUnitState(UNIT_STATE_CASTING))
{
return; return;
}
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_DOUBLE_BREATH:
if (me->IsWithinDist(me->GetVictim(), ATTACK_DISTANCE))
DoCastVictim(SPELL_DOUBLE_BREATH);
events.ScheduleEvent(EVENT_DOUBLE_BREATH, urand(10000, 20000));
break;
case EVENT_STOMP:
DoCastAOE(SPELL_STOMP);
events.ScheduleEvent(EVENT_STOMP, urand(14000, 24000));
break;
}
}
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
private: private:
EventMap events; TaskScheduler _scheduler;
};
}; };
void AddSC_boss_nexusprince_shaffar() void AddSC_boss_nexusprince_shaffar()
{ {
new boss_nexusprince_shaffar(); RegisterManaTombsCreatureAI(boss_nexusprince_shaffar);
new npc_yor(); RegisterManaTombsCreatureAI(npc_yor);
} }
@@ -23,8 +23,7 @@ enum Spells
{ {
SPELL_EARTHQUAKE = 33919, SPELL_EARTHQUAKE = 33919,
SPELL_CRYSTAL_PRISON = 32361, SPELL_CRYSTAL_PRISON = 32361,
SPELL_ARCING_SMASH_N = 8374, SPELL_ARCING_SMASH = 8374
SPELL_ARCING_SMASH_H = 38761
}; };
struct boss_tavarok : public BossAI struct boss_tavarok : public BossAI
@@ -45,7 +44,6 @@ struct boss_tavarok : public BossAI
void JustEngagedWith(Unit* /*who*/) override void JustEngagedWith(Unit* /*who*/) override
{ {
_JustEngagedWith(); _JustEngagedWith();
scheduler.Schedule(10s, 14200ms, [this](TaskContext context) scheduler.Schedule(10s, 14200ms, [this](TaskContext context)
{ {
DoCastSelf(SPELL_EARTHQUAKE); DoCastSelf(SPELL_EARTHQUAKE);
@@ -56,7 +54,7 @@ struct boss_tavarok : public BossAI
context.Repeat(15s, 22s); context.Repeat(15s, 22s);
}).Schedule(5900ms, [this](TaskContext context) }).Schedule(5900ms, [this](TaskContext context)
{ {
DoCastVictim(DUNGEON_MODE(SPELL_ARCING_SMASH_N, SPELL_ARCING_SMASH_H)); DoCastVictim(SPELL_ARCING_SMASH);
context.Repeat(8s, 12s); context.Repeat(8s, 12s);
}); });
} }
@@ -66,9 +64,7 @@ struct boss_tavarok : public BossAI
_JustDied(); _JustDied();
} }
void KilledUnit(Unit* /*victim*/) override void KilledUnit(Unit* /*victim*/) override {}
{
}
}; };
void AddSC_boss_tavarok() void AddSC_boss_tavarok()
@@ -20,23 +20,25 @@
#include "SpellScript.h" #include "SpellScript.h"
#include "sethekk_halls.h" #include "sethekk_halls.h"
enum Anzu enum Text
{ {
SAY_ANZU_INTRO1 = 0, SAY_ANZU_INTRO1 = 0,
SAY_ANZU_INTRO2 = 1, SAY_ANZU_INTRO2 = 1,
SAY_SUMMON = 2, SAY_SUMMON = 2
};
enum Spells
{
SPELL_PARALYZING_SCREECH = 40184, SPELL_PARALYZING_SCREECH = 40184,
SPELL_SPELL_BOMB = 40303, SPELL_SPELL_BOMB = 40303,
SPELL_CYCLONE = 40321, SPELL_CYCLONE = 40321,
SPELL_BANISH_SELF = 42354, SPELL_BANISH_SELF = 42354,
SPELL_SHADOWFORM = 40973, SPELL_SHADOWFORM = 40973
};
EVENT_SPELL_SCREECH = 1, enum Npc
EVENT_SPELL_BOMB = 2, {
EVENT_SPELL_CYCLONE = 3, NPC_BROOD_OF_ANZU = 23132
EVENT_ANZU_HEALTH1 = 4,
EVENT_ANZU_HEALTH2 = 5
}; };
struct boss_anzu : public BossAI struct boss_anzu : public BossAI
@@ -46,6 +48,10 @@ struct boss_anzu : public BossAI
talkTimer = 1; talkTimer = 1;
me->ReplaceAllUnitFlags(UNIT_FLAG_NON_ATTACKABLE); me->ReplaceAllUnitFlags(UNIT_FLAG_NON_ATTACKABLE);
me->AddAura(SPELL_SHADOWFORM, me); me->AddAura(SPELL_SHADOWFORM, me);
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
} }
uint32 talkTimer; uint32 talkTimer;
@@ -55,18 +61,45 @@ struct boss_anzu : public BossAI
summons.Despawn(summon); summons.Despawn(summon);
summons.RemoveNotExisting(); summons.RemoveNotExisting();
if (summons.empty()) if (summons.empty())
{
me->RemoveAurasDueToSpell(SPELL_BANISH_SELF); me->RemoveAurasDueToSpell(SPELL_BANISH_SELF);
} }
}
void Reset() override
{
_Reset();
ScheduleHealthCheckEvent({ 66, 33 }, [&] {
SummonBroods();
scheduler.DelayAll(10s);
});
}
void JustEngagedWith(Unit* /*who*/) override void JustEngagedWith(Unit* /*who*/) override
{ {
_JustEngagedWith(); _JustEngagedWith();
events.Reset(); scheduler.Schedule(14s, [this](TaskContext context)
events.ScheduleEvent(EVENT_SPELL_SCREECH, 14000); {
events.ScheduleEvent(EVENT_SPELL_BOMB, 5000); DoCastSelf(SPELL_PARALYZING_SCREECH);
events.ScheduleEvent(EVENT_SPELL_CYCLONE, 8000); context.Repeat(23s);
events.ScheduleEvent(EVENT_ANZU_HEALTH1, 2000); scheduler.DelayAll(3s);
events.ScheduleEvent(EVENT_ANZU_HEALTH2, 2001); }).Schedule(5s, [this](TaskContext context)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
{
DoCast(target, SPELL_SPELL_BOMB);
}
context.Repeat(16s, 24500ms);
scheduler.DelayAll(3s);
}).Schedule(8s, [this](TaskContext context)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 45.0f, true))
{
DoCast(target, SPELL_CYCLONE);
}
context.Repeat(22s, 27s);
scheduler.DelayAll(3s);
});
} }
void SummonBroods() void SummonBroods()
@@ -74,7 +107,9 @@ struct boss_anzu : public BossAI
Talk(SAY_SUMMON); Talk(SAY_SUMMON);
me->CastSpell(me, SPELL_BANISH_SELF, true); me->CastSpell(me, SPELL_BANISH_SELF, true);
for (uint8 i = 0; i < 5; ++i) for (uint8 i = 0; i < 5; ++i)
me->SummonCreature(23132 /*NPC_BROOD_OF_ANZU*/, me->GetPositionX() + 20 * cos((float)i), me->GetPositionY() + 20 * std::sin((float)i), me->GetPositionZ() + 25.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); {
me->SummonCreature(NPC_BROOD_OF_ANZU, me->GetPositionX() + 20 * cos((float)i), me->GetPositionY() + 20 * std::sin((float)i), me->GetPositionZ() + 25.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
}
} }
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
@@ -99,49 +134,10 @@ struct boss_anzu : public BossAI
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
events.Update(diff); scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING | UNIT_STATE_STUNNED)) if (me->HasUnitState(UNIT_STATE_CASTING | UNIT_STATE_STUNNED))
return; return;
switch (events.ExecuteEvent())
{
case EVENT_SPELL_SCREECH:
me->CastSpell(me, SPELL_PARALYZING_SCREECH, false);
events.RepeatEvent(23000);
events.DelayEvents(3000);
break;
case EVENT_SPELL_BOMB:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
me->CastSpell(target, SPELL_SPELL_BOMB, false);
events.RepeatEvent(urand(16000, 24500));
events.DelayEvents(3000);
break;
case EVENT_SPELL_CYCLONE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 45.0f, true))
me->CastSpell(target, SPELL_CYCLONE, false);
events.RepeatEvent(urand(22000, 27000));
events.DelayEvents(3000);
break;
case EVENT_ANZU_HEALTH1:
if (me->HealthBelowPct(66))
{
SummonBroods();
events.DelayEvents(10000);
return;
}
events.RepeatEvent(1000);
break;
case EVENT_ANZU_HEALTH2:
if (me->HealthBelowPct(33))
{
SummonBroods();
events.DelayEvents(10000);
return;
}
events.RepeatEvent(1000);
break;
}
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
@@ -19,24 +19,6 @@
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "sethekk_halls.h" #include "sethekk_halls.h"
enum Spells
{
SPELL_FLAME_SHOCK_N = 15039,
SPELL_FLAME_SHOCK_H = 15616,
SPELL_ARCANE_SHOCK_N = 33534,
SPELL_ARCANE_SHOCK_H = 38135,
SPELL_FROST_SHOCK_N = 12548,
SPELL_FROST_SHOCK_H = 21401,
SPELL_SHADOW_SHOCK_N = 33620,
SPELL_SHADOW_SHOCK_H = 38137,
SPELL_CHAIN_LIGHTNING_N = 15659,
SPELL_CHAIN_LIGHTNING_H = 15305,
SPELL_SUMMON_ARC_ELE = 33538,
SPELL_SUMMON_FIRE_ELE = 33537,
SPELL_SUMMON_FROST_ELE = 33539,
SPELL_SUMMON_SHADOW_ELE = 33540
};
enum Text enum Text
{ {
SAY_SUMMON = 0, SAY_SUMMON = 0,
@@ -45,6 +27,19 @@ enum Text
SAY_DEATH = 3 SAY_DEATH = 3
}; };
enum Spells
{
SPELL_FLAME_SHOCK = 15039,
SPELL_ARCANE_SHOCK = 33534,
SPELL_FROST_SHOCK = 12548,
SPELL_SHADOW_SHOCK = 33620,
SPELL_CHAIN_LIGHTNING = 15659,
SPELL_SUMMON_ARC_ELE = 33538,
SPELL_SUMMON_FIRE_ELE = 33537,
SPELL_SUMMON_FROST_ELE = 33539,
SPELL_SUMMON_SHADOW_ELE = 33540
};
struct boss_darkweaver_syth : public BossAI struct boss_darkweaver_syth : public BossAI
{ {
boss_darkweaver_syth(Creature* creature) : BossAI(creature, DATA_DARKWEAVER_SYTH) boss_darkweaver_syth(Creature* creature) : BossAI(creature, DATA_DARKWEAVER_SYTH)
@@ -58,7 +53,6 @@ struct boss_darkweaver_syth : public BossAI
void Reset() override void Reset() override
{ {
_Reset(); _Reset();
ScheduleHealthCheckEvent({90, 50, 10}, [&] { ScheduleHealthCheckEvent({90, 50, 10}, [&] {
Talk(SAY_SUMMON); Talk(SAY_SUMMON);
DoCastSelf(SPELL_SUMMON_ARC_ELE); DoCastSelf(SPELL_SUMMON_ARC_ELE);
@@ -72,26 +66,25 @@ struct boss_darkweaver_syth : public BossAI
{ {
_JustEngagedWith(); _JustEngagedWith();
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
scheduler.Schedule(2s, [this](TaskContext context) scheduler.Schedule(2s, [this](TaskContext context)
{ {
DoCastRandomTarget(DUNGEON_MODE(SPELL_FLAME_SHOCK_N, SPELL_FLAME_SHOCK_H)); DoCastRandomTarget(SPELL_FLAME_SHOCK);
context.Repeat(10s, 15s); context.Repeat(10s, 15s);
}).Schedule(4s, [this](TaskContext context) }).Schedule(4s, [this](TaskContext context)
{ {
DoCastRandomTarget(DUNGEON_MODE(SPELL_ARCANE_SHOCK_N, SPELL_ARCANE_SHOCK_H)); DoCastRandomTarget(SPELL_ARCANE_SHOCK);
context.Repeat(10s, 15s); context.Repeat(10s, 15s);
}).Schedule(6s, [this](TaskContext context) }).Schedule(6s, [this](TaskContext context)
{ {
DoCastRandomTarget(DUNGEON_MODE(SPELL_FROST_SHOCK_N, SPELL_FROST_SHOCK_H)); DoCastRandomTarget(SPELL_FROST_SHOCK);
context.Repeat(10s, 15s); context.Repeat(10s, 15s);
}).Schedule(8s, [this](TaskContext context) }).Schedule(8s, [this](TaskContext context)
{ {
DoCastRandomTarget(DUNGEON_MODE(SPELL_SHADOW_SHOCK_N, SPELL_SHADOW_SHOCK_H)); DoCastRandomTarget(SPELL_SHADOW_SHOCK);
context.Repeat(10s, 15s); context.Repeat(10s, 15s);
}).Schedule(15s, [this](TaskContext context) }).Schedule(15s, [this](TaskContext context)
{ {
DoCastRandomTarget(DUNGEON_MODE(SPELL_CHAIN_LIGHTNING_N, SPELL_CHAIN_LIGHTNING_H)); DoCastRandomTarget(SPELL_CHAIN_LIGHTNING);
context.Repeat(10s, 15s); context.Repeat(10s, 15s);
}); });
} }
@@ -99,14 +92,16 @@ struct boss_darkweaver_syth : public BossAI
void JustDied(Unit* /*killer*/) override void JustDied(Unit* /*killer*/) override
{ {
_JustDied(); _JustDied();
Talk(SAY_DEATH); Talk(SAY_DEATH);
} }
void KilledUnit(Unit* /*victim*/) override void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
{ {
Talk(SAY_SLAY); Talk(SAY_SLAY);
} }
}
}; };
void AddSC_boss_darkweaver_syth() void AddSC_boss_darkweaver_syth()
@@ -20,13 +20,13 @@
#include "SpellScript.h" #include "SpellScript.h"
#include "sethekk_halls.h" #include "sethekk_halls.h"
enum TailonkingIkiss enum Text
{ {
SAY_INTRO = 0, SAY_INTRO = 0,
SAY_AGGRO = 1, SAY_AGGRO = 1,
SAY_SLAY = 2, SAY_SLAY = 2,
SAY_DEATH = 3, SAY_DEATH = 3,
EMOTE_ARCANE_EXP = 4, EMOTE_ARCANE_EXP = 4
}; };
enum Spells enum Spells
@@ -38,7 +38,7 @@ enum Spells
SPELL_SLOW = 35032, SPELL_SLOW = 35032,
SPELL_POLYMORPH = 38245, SPELL_POLYMORPH = 38245,
SPELL_ARCANE_VOLLEY = 35059, SPELL_ARCANE_VOLLEY = 35059,
SPELL_ARCANE_EXPLOSION = 38197, SPELL_ARCANE_EXPLOSION = 38197
}; };
struct boss_talon_king_ikiss : public BossAI struct boss_talon_king_ikiss : public BossAI
@@ -55,14 +55,12 @@ struct boss_talon_king_ikiss : public BossAI
{ {
_Reset(); _Reset();
_spoken = false; _spoken = false;
ScheduleHealthCheckEvent({ 80, 50, 25 }, [&] { ScheduleHealthCheckEvent({ 80, 50, 25 }, [&] {
me->InterruptNonMeleeSpells(false); me->InterruptNonMeleeSpells(false);
DoCastAOE(SPELL_BLINK); DoCastAOE(SPELL_BLINK);
DoCastSelf(SPELL_ARCANE_BUBBLE, true); DoCastSelf(SPELL_ARCANE_BUBBLE, true);
Talk(EMOTE_ARCANE_EXP); Talk(EMOTE_ARCANE_EXP);
scheduler.Schedule(1s, [this](TaskContext /*context*/)
scheduler.Schedule(1s, [this](TaskContext)
{ {
DoCastAOE(SPELL_ARCANE_EXPLOSION); DoCastAOE(SPELL_ARCANE_EXPLOSION);
}).Schedule(6500ms, [this](TaskContext /*context*/) }).Schedule(6500ms, [this](TaskContext /*context*/)
@@ -72,7 +70,7 @@ struct boss_talon_king_ikiss : public BossAI
}); });
ScheduleHealthCheckEvent(20, [&] { ScheduleHealthCheckEvent(20, [&] {
DoCast(me, SPELL_MANA_SHIELD); DoCastSelf(SPELL_MANA_SHIELD);
}); });
} }
@@ -89,7 +87,6 @@ struct boss_talon_king_ikiss : public BossAI
Talk(SAY_INTRO); Talk(SAY_INTRO);
_spoken = true; _spoken = true;
} }
ScriptedAI::MoveInLineOfSight(who); ScriptedAI::MoveInLineOfSight(who);
} }
@@ -97,7 +94,6 @@ struct boss_talon_king_ikiss : public BossAI
{ {
_JustEngagedWith(); _JustEngagedWith();
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
scheduler.Schedule(5s, [this](TaskContext context) scheduler.Schedule(5s, [this](TaskContext context)
{ {
DoCastAOE(SPELL_ARCANE_VOLLEY); DoCastAOE(SPELL_ARCANE_VOLLEY);
@@ -114,7 +110,6 @@ struct boss_talon_king_ikiss : public BossAI
} }
context.Repeat(15s, 17500ms); context.Repeat(15s, 17500ms);
}); });
if (IsHeroic()) if (IsHeroic())
{ {
scheduler.Schedule(15s, 25s, [this](TaskContext context) scheduler.Schedule(15s, 25s, [this](TaskContext context)
@@ -129,18 +124,19 @@ struct boss_talon_king_ikiss : public BossAI
{ {
_JustDied(); _JustDied();
Talk(SAY_DEATH); Talk(SAY_DEATH);
if (GameObject* coffer = instance->GetGameObject(DATA_GO_TALON_KING_COFFER)) if (GameObject* coffer = instance->GetGameObject(DATA_GO_TALON_KING_COFFER))
{ {
coffer->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE | GO_FLAG_INTERACT_COND); coffer->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE | GO_FLAG_INTERACT_COND);
} }
} }
void KilledUnit(Unit* /*victim*/) override void KilledUnit(Unit* victim) override
{
if (victim->IsPlayer() && urand(0, 1))
{ {
if (urand(0, 1))
Talk(SAY_SLAY); Talk(SAY_SLAY);
} }
}
private: private:
bool _spoken; bool _spoken;
@@ -19,23 +19,25 @@
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "shadow_labyrinth.h" #include "shadow_labyrinth.h"
enum eEnums enum Text
{ {
SAY_INTRO = 0, SAY_INTRO = 0,
SAY_AGGRO = 1, SAY_AGGRO = 1,
SAY_HELP = 2, SAY_HELP = 2,
SAY_SLAY = 3, SAY_SLAY = 3,
SAY_DEATH = 4, SAY_DEATH = 4
};
enum Spells
{
SPELL_BANISH = 30231, SPELL_BANISH = 30231,
SPELL_CORROSIVE_ACID = 33551, SPELL_CORROSIVE_ACID = 33551,
SPELL_FEAR = 33547, SPELL_FEAR = 33547,
SPELL_ENRAGE = 34970, SPELL_ENRAGE = 34970
};
EVENT_SPELL_CORROSIVE = 1,
EVENT_SPELL_FEAR = 2,
EVENT_SPELL_ENRAGE = 3,
enum Misc
{
PATH_ID_START = 1873100, PATH_ID_START = 1873100,
PATH_ID_PATHING = 1873101, PATH_ID_PATHING = 1873101,
@@ -81,7 +83,6 @@ struct boss_ambassador_hellmaw : public BossAI
{ {
return; return;
} }
me->RemoveAurasDueToSpell(SPELL_BANISH); me->RemoveAurasDueToSpell(SPELL_BANISH);
Talk(SAY_INTRO); Talk(SAY_INTRO);
DoPlaySoundToSet(me, SOUND_INTRO); DoPlaySoundToSet(me, SOUND_INTRO);
@@ -96,9 +97,7 @@ struct boss_ambassador_hellmaw : public BossAI
{ {
return; return;
} }
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
scheduler.Schedule(23050ms, 30350ms, [this](TaskContext context) scheduler.Schedule(23050ms, 30350ms, [this](TaskContext context)
{ {
DoCastVictim(SPELL_CORROSIVE_ACID); DoCastVictim(SPELL_CORROSIVE_ACID);
@@ -111,12 +110,11 @@ struct boss_ambassador_hellmaw : public BossAI
if (IsHeroic()) if (IsHeroic())
{ {
scheduler.Schedule(3min, [this](TaskContext) scheduler.Schedule(3min, [this](TaskContext /*context*/)
{ {
DoCastSelf(SPELL_ENRAGE, true); DoCastSelf(SPELL_ENRAGE, true);
}); });
} }
_JustEngagedWith(); _JustEngagedWith();
} }
@@ -126,7 +124,6 @@ struct boss_ambassador_hellmaw : public BossAI
{ {
return; return;
} }
ScriptedAI::MoveInLineOfSight(who); ScriptedAI::MoveInLineOfSight(who);
} }
@@ -136,7 +133,6 @@ struct boss_ambassador_hellmaw : public BossAI
{ {
return; return;
} }
ScriptedAI::AttackStart(who); ScriptedAI::AttackStart(who);
} }
@@ -199,7 +195,6 @@ struct boss_ambassador_hellmaw : public BossAI
me->setAttackTimer(OFF_ATTACK, ATTACK_DISPLAY_DELAY); me->setAttackTimer(OFF_ATTACK, ATTACK_DISPLAY_DELAY);
} }
} }
me->AttackerStateUpdate(victim, BASE_ATTACK, false, ignoreCasting); me->AttackerStateUpdate(victim, BASE_ATTACK, false, ignoreCasting);
me->resetAttackTimer(); me->resetAttackTimer();
} }
@@ -211,7 +206,6 @@ struct boss_ambassador_hellmaw : public BossAI
{ {
me->setAttackTimer(BASE_ATTACK, ATTACK_DISPLAY_DELAY); me->setAttackTimer(BASE_ATTACK, ATTACK_DISPLAY_DELAY);
} }
me->AttackerStateUpdate(victim, OFF_ATTACK, false, ignoreCasting); me->AttackerStateUpdate(victim, OFF_ATTACK, false, ignoreCasting);
me->resetAttackTimer(OFF_ATTACK); me->resetAttackTimer(OFF_ATTACK);
} }
@@ -19,32 +19,38 @@
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "shadow_labyrinth.h" #include "shadow_labyrinth.h"
enum BlackheartTheInciter enum Text
{ {
SPELL_INCITE_CHAOS = 33676,
SPELL_INCITE_CHAOS_B = 33684, //debuff applied to each member of party
SPELL_CHARGE = 33709,
SPELL_WAR_STOMP = 33707,
SPELL_LAUGHTER = 33722,
SAY_INTRO = 0, SAY_INTRO = 0,
SAY_AGGRO = 1, SAY_AGGRO = 1,
SAY_SLAY = 2, SAY_SLAY = 2,
SAY_HELP = 3, SAY_HELP = 3,
SAY_DEATH = 4, SAY_DEATH = 4
};
EVENT_SPELL_INCITE = 1, enum Spells
EVENT_INCITE_WAIT = 2, {
EVENT_SPELL_CHARGE = 3, SPELL_INCITE_CHAOS = 33676,
EVENT_SPELL_KNOCKBACK = 4, SPELL_INCITE_CHAOS_B = 33684, // debuff applied to each player
EVENT_SPELL_WAR_STOMP = 5, SPELL_CHARGE = 33709,
SPELL_WAR_STOMP = 33707,
SPELL_LAUGHTER = 33722
};
enum Npc
{
NPC_INCITE_TRIGGER = 19300 NPC_INCITE_TRIGGER = 19300
}; };
struct boss_blackheart_the_inciter : public BossAI struct boss_blackheart_the_inciter : public BossAI
{ {
boss_blackheart_the_inciter(Creature* creature) : BossAI(creature, DATA_BLACKHEARTTHEINCITEREVENT) { } boss_blackheart_the_inciter(Creature* creature) : BossAI(creature, DATA_BLACKHEARTTHEINCITEREVENT)
{
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
bool InciteChaos; bool InciteChaos;
@@ -72,12 +78,48 @@ struct boss_blackheart_the_inciter : public BossAI
void JustEngagedWith(Unit* /*who*/) override void JustEngagedWith(Unit* /*who*/) override
{ {
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
me->CallForHelp(100.0f);
events.ScheduleEvent(EVENT_SPELL_INCITE, 24000);
events.ScheduleEvent(EVENT_INCITE_WAIT, 15000);
events.ScheduleEvent(EVENT_SPELL_CHARGE, urand(30000, 50000));
events.ScheduleEvent(EVENT_SPELL_WAR_STOMP, urand(16950, 26350));
_JustEngagedWith(); _JustEngagedWith();
me->CallForHelp(100.0f);
scheduler.Schedule(24s, [this](TaskContext context)
{
DoCastAOE(SPELL_INCITE_CHAOS);
DoCastSelf(SPELL_LAUGHTER, true);
uint32 inciteTriggerID = NPC_INCITE_TRIGGER;
std::list<HostileReference*> t_list = me->GetThreatMgr().GetThreatList();
for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr != t_list.end(); ++itr)
{
Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
if (target && target->IsPlayer())
{
if (Creature* inciteTrigger = me->SummonCreature(inciteTriggerID++, *target, TEMPSUMMON_TIMED_DESPAWN, 15 * IN_MILLISECONDS))
{
inciteTrigger->CastSpell(target, SPELL_INCITE_CHAOS_B, true);
}
}
}
DoResetThreatList();
me->SetImmuneToPC(true);
InciteChaos = true;
scheduler.DelayAll(15s);
context.Repeat(50s, 70s);
scheduler.Schedule(15s, [this](TaskContext /*context*/)
{
me->SetImmuneToPC(false);
InciteChaos = false;
});
}).Schedule(15s, [this](TaskContext /*context*/)
{
me->SetImmuneToPC(false);
InciteChaos = false;
}).Schedule(30s, 50s, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_CHARGE);
context.Repeat(30s, 50s);
}).Schedule(16950ms, 26350ms, [this](TaskContext context)
{
DoCastAOE(SPELL_WAR_STOMP);
context.Repeat(16950ms, 26350ms);
});
} }
void EnterEvadeMode(EvadeReason why) override void EnterEvadeMode(EvadeReason why) override
@@ -91,55 +133,9 @@ struct boss_blackheart_the_inciter : public BossAI
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
if (!UpdateVictim() && !InciteChaos) if (!UpdateVictim() && !InciteChaos)
{
return; return;
}
events.Update(diff);
switch (events.ExecuteEvent())
{
case EVENT_INCITE_WAIT:
me->SetImmuneToPC(false);
InciteChaos = false;
break;
case EVENT_SPELL_INCITE:
{
DoCastAOE(SPELL_INCITE_CHAOS);
DoCastSelf(SPELL_LAUGHTER, true);
uint32 inciteTriggerID = NPC_INCITE_TRIGGER;
std::list<HostileReference*> t_list = me->GetThreatMgr().GetThreatList();
for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr != t_list.end(); ++itr)
{
Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
if (target && target->IsPlayer())
{
if (Creature* inciteTrigger = me->SummonCreature(inciteTriggerID++, *target, TEMPSUMMON_TIMED_DESPAWN, 15 * IN_MILLISECONDS))
{
inciteTrigger->CastSpell(target, SPELL_INCITE_CHAOS_B, true);
}
}
}
DoResetThreatList();
me->SetImmuneToPC(true);
InciteChaos = true;
events.DelayEvents(15000);
events.RepeatEvent(urand(50000, 70000));
events.ScheduleEvent(EVENT_INCITE_WAIT, 15000);
break;
}
case EVENT_SPELL_CHARGE:
DoCastRandomTarget(SPELL_CHARGE);
events.RepeatEvent(urand(30000, 50000));
break;
case EVENT_SPELL_WAR_STOMP:
DoCastAOE(SPELL_WAR_STOMP);
events.RepeatEvent(urand(16950, 26350));
break;
}
scheduler.Update(diff);
if (InciteChaos) if (InciteChaos)
return; return;
@@ -20,27 +20,35 @@
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "shadow_labyrinth.h" #include "shadow_labyrinth.h"
enum GrandmasterVorpil enum Text
{ {
SAY_INTRO = 0, SAY_INTRO = 0,
SAY_AGGRO = 1, SAY_AGGRO = 1,
SAY_HELP = 2, SAY_HELP = 2,
SAY_SLAY = 3, SAY_SLAY = 3,
SAY_DEATH = 4, SAY_DEATH = 4
};
enum Spells
{
// Vorpil
SPELL_RAIN_OF_FIRE = 33617, SPELL_RAIN_OF_FIRE = 33617,
SPELL_DRAW_SHADOWS = 33563, SPELL_DRAW_SHADOWS = 33563,
SPELL_SHADOWBOLT_VOLLEY = 33841, SPELL_SHADOWBOLT_VOLLEY = 33841,
SPELL_BANISH = 38791, SPELL_BANISH = 38791,
NPC_VOID_TRAVELER = 19226, // Void Traveler
SPELL_SACRIFICE = 33587, SPELL_SACRIFICE = 33587,
SPELL_SHADOW_NOVA = 33846, SPELL_SHADOW_NOVA = 33846,
SPELL_EMPOWERING_SHADOWS = 33783, SPELL_EMPOWERING_SHADOWS = 33783,
NPC_VOID_PORTAL = 19224, SPELL_VOID_PORTAL_VISUAL = 33569
SPELL_VOID_PORTAL_VISUAL = 33569, };
enum Npc
{
NPC_VOID_TRAVELER = 19226,
NPC_VOID_PORTAL = 19224
}; };
float VorpilPosition[3] = {-253.548f, -263.646f, 17.0864f}; float VorpilPosition[3] = {-253.548f, -263.646f, 17.0864f};
@@ -57,10 +65,7 @@ float VoidPortalCoords[5][4] =
struct boss_grandmaster_vorpil : public BossAI struct boss_grandmaster_vorpil : public BossAI
{ {
boss_grandmaster_vorpil(Creature* creature) : BossAI(creature, DATA_GRANDMASTER_VORPIL) boss_grandmaster_vorpil(Creature* creature) : BossAI(creature, DATA_GRANDMASTER_VORPIL), sayIntro(false) {}
{
sayIntro = false;
}
bool sayIntro, sayHelp; bool sayIntro, sayHelp;
@@ -111,7 +116,6 @@ struct boss_grandmaster_vorpil : public BossAI
default: default:
return 4800ms; return 4800ms;
} }
return 1s; return 1s;
} }
@@ -146,7 +150,6 @@ struct boss_grandmaster_vorpil : public BossAI
{ {
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
summonPortals(); summonPortals();
scheduler.Schedule(9700ms, 20s, [this](TaskContext context) scheduler.Schedule(9700ms, 20s, [this](TaskContext context)
{ {
DoCastAOE(SPELL_SHADOWBOLT_VOLLEY); DoCastAOE(SPELL_SHADOWBOLT_VOLLEY);
@@ -20,10 +20,8 @@
#include "SpellInfo.h" #include "SpellInfo.h"
#include "shadow_labyrinth.h" #include "shadow_labyrinth.h"
enum Murmur enum Spells
{ {
EMOTE_SONIC_BOOM = 0,
SPELL_SUPPRESSION = 33332, SPELL_SUPPRESSION = 33332,
SPELL_SHOCKWAVE = 33686, SPELL_SHOCKWAVE = 33686,
SPELL_SHOCKWAVE_SERVERSIDE = 33673, SPELL_SHOCKWAVE_SERVERSIDE = 33673,
@@ -34,12 +32,14 @@ enum Murmur
SPELL_MURMUR_WRATH_AOE = 33329, SPELL_MURMUR_WRATH_AOE = 33329,
SPELL_MURMUR_WRATH = 33331, SPELL_MURMUR_WRATH = 33331,
SPELL_SONIC_BOOM_CAST_N = 33923, SPELL_SONIC_BOOM_CAST = 33923,
SPELL_SONIC_BOOM_CAST_H = 38796, SPELL_SONIC_BOOM_EFFECT = 38795,
SPELL_SONIC_BOOM_EFFECT_N = 38795, SPELL_MURMURS_TOUCH = 33711
SPELL_SONIC_BOOM_EFFECT_H = 33666, };
SPELL_MURMURS_TOUCH_N = 33711,
SPELL_MURMURS_TOUCH_H = 38794, enum Misc
{
EMOTE_SONIC_BOOM = 0,
GROUP_RESONANCE = 1, GROUP_RESONANCE = 1,
GROUP_OOC_CAST = 2, GROUP_OOC_CAST = 2,
@@ -47,7 +47,7 @@ enum Murmur
GUID_MURMUR_NPCS = 1 GUID_MURMUR_NPCS = 1
}; };
enum Creatures enum Npc
{ {
NPC_CABAL_SPELLBINDER = 18639 NPC_CABAL_SPELLBINDER = 18639
}; };
@@ -57,7 +57,6 @@ struct boss_murmur : public BossAI
boss_murmur(Creature* creature) : BossAI(creature, DATA_MURMUR) boss_murmur(Creature* creature) : BossAI(creature, DATA_MURMUR)
{ {
SetCombatMovement(false); SetCombatMovement(false);
scheduler.SetValidator([this] scheduler.SetValidator([this]
{ {
return !me->HasUnitState(UNIT_STATE_CASTING); return !me->HasUnitState(UNIT_STATE_CASTING);
@@ -75,7 +74,6 @@ struct boss_murmur : public BossAI
void CastSupressionOOC() void CastSupressionOOC()
{ {
me->m_Events.CancelEventGroup(GROUP_OOC_CAST); me->m_Events.CancelEventGroup(GROUP_OOC_CAST);
me->m_Events.AddEventAtOffset([this] { me->m_Events.AddEventAtOffset([this] {
if (me->FindNearestCreature(NPC_CABAL_SPELLBINDER, 35.0f)) if (me->FindNearestCreature(NPC_CABAL_SPELLBINDER, 35.0f))
{ {
@@ -106,13 +104,11 @@ struct boss_murmur : public BossAI
{ {
return true; return true;
} }
if (Unit* victimTarget = victim->GetVictim()) if (Unit* victimTarget = victim->GetVictim())
{ {
return victimTarget != me; return victimTarget != me;
} }
} }
return true; return true;
} }
@@ -133,23 +129,21 @@ struct boss_murmur : public BossAI
{ {
return; return;
} }
_JustEngagedWith(); _JustEngagedWith();
scheduler.Schedule(28s, [this](TaskContext context) scheduler.Schedule(28s, [this](TaskContext context)
{ {
Talk(EMOTE_SONIC_BOOM); Talk(EMOTE_SONIC_BOOM);
DoCastAOE(DUNGEON_MODE(SPELL_SONIC_BOOM_CAST_N, SPELL_SONIC_BOOM_CAST_H)); DoCastAOE(SPELL_SONIC_BOOM_CAST);
scheduler.Schedule(1500ms, [this](TaskContext) scheduler.Schedule(1500ms, [this](TaskContext)
{ {
DoCastAOE(DUNGEON_MODE(SPELL_SONIC_BOOM_EFFECT_N, SPELL_SONIC_BOOM_EFFECT_H), true); DoCastAOE(SPELL_SONIC_BOOM_EFFECT, true);
}); });
context.Repeat(34s, 40s); context.Repeat(34s, 40s);
}).Schedule(14600ms, 25500ms, [this](TaskContext context) }).Schedule(14600ms, 25500ms, [this](TaskContext context)
{ {
DoCastRandomTarget(DUNGEON_MODE(SPELL_MURMURS_TOUCH_N, SPELL_MURMURS_TOUCH_H)); DoCastRandomTarget(SPELL_MURMURS_TOUCH);
context.Repeat(14600ms, 25500ms); context.Repeat(14600ms, 25500ms);
}).Schedule(15s, 30s, [this](TaskContext context) }).Schedule(15s, 30s, [this](TaskContext context)
{ {
@@ -177,7 +171,6 @@ struct boss_murmur : public BossAI
}); });
} }
} }
context.Repeat(); context.Repeat();
}); });
@@ -193,7 +186,6 @@ struct boss_murmur : public BossAI
context.Repeat(3650ms, 9150ms); context.Repeat(3650ms, 9150ms);
}); });
} }
me->m_Events.CancelEventGroup(GROUP_OOC_CAST); me->m_Events.CancelEventGroup(GROUP_OOC_CAST);
} }
}; };