Core/Scripts: Illidari Council Rewrite (#18546)

Thanks to Sirikfoll, Krudor and Offl for all help

(cherry picked from commit 5af1fa2273)
This commit is contained in:
Keader
2017-01-01 21:11:15 -02:00
committed by DoctorKraft
parent 7d96b98d51
commit 36910585c9
5 changed files with 1038 additions and 953 deletions

View File

@@ -0,0 +1,73 @@
DELETE FROM `creature` WHERE `id` IN(22952,22950,22949,22951);
DELETE FROM `creature_summon_groups` WHERE `summonerId`=23426; -- Illidari Council Trigger
INSERT INTO `creature_summon_groups` (`summonerId`,`summonerType`,`groupId`,`entry`,`position_x`,`position_y`,`position_z`,`orientation`,`summonType`,`summonTime`) VALUES
(23426,0,1,22952,697.495,310.651,277.527,3.1765 ,6,3600000), -- Veras Darkshadow
(23426,0,1,22950,700.792,307.192,277.526,3.14159,6,3600000), -- High Nethermancer Zerevor
(23426,0,1,22949,700.739,302.722,277.526,3.10669,6,3600000), -- Gathios the Shatterer
(23426,0,1,22951,697.409,299.377,277.526,3.07178,6,3600000); -- Lady Malande
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=41333; -- Empyreal Equivalency
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(13,1,41333,0,0,31,0,3,22950,0,0,0,0,'','Effect_0 hits High Nethermancer Zerevor'),
(13,1,41333,0,1,31,0,3,22949,0,0,0,0,'','Effect_0 hits Gathios the Shatterer'),
(13,1,41333,0,2,31,0,3,22951,0,0,0,0,'','Effect_0 hits Lady Malande'),
(13,1,41333,0,3,31,0,3,22952,0,0,0,0,'','Effect_0 hits Veras Darkshadow');
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=41499; -- Empyreal Balance
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(13,1,41499,0,0,31,0,3,22950,0,0,0,0,'','Effect_0 hits High Nethermancer Zerevor'),
(13,1,41499,0,1,31,0,3,22949,0,0,0,0,'','Effect_0 hits Gathios the Shatterer'),
(13,1,41499,0,2,31,0,3,22951,0,0,0,0,'','Effect_0 hits Lady Malande'),
(13,1,41499,0,3,31,0,3,22952,0,0,0,0,'','Effect_0 hits Veras Darkshadow');
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=41342; -- Shared Rule
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(13,1,41342,0,0,31,0,3,23426,0,0,0,0,'','Effect_0 hits The Illidari Council');
UPDATE `linked_respawn` SET `linkedGuid`=52479 WHERE `linkedGuid`=52762;
UPDATE `creature_template` SET `flags_extra`=`flags_extra`|128, `ScriptName`='npc_veras_vanish_effect' WHERE `entry`=23451;
UPDATE `creature_template` SET `ScriptName`='boss_illidari_council' WHERE `entry`=23426;
UPDATE `creature_template` SET `ScriptName`='' WHERE `entry`=23499;
DELETE FROM `spell_script_names` WHERE `ScriptName` IN(
'spell_illidari_council_empyreal_balance',
'spell_illidari_council_empyreal_equivalency',
'spell_illidari_council_balance_of_power',
'spell_illidari_council_deadly_strike',
'spell_illidari_council_deadly_poison',
'spell_illidari_council_judgement',
'spell_illidari_council_seal',
'spell_boss_lady_malande_shield',
'spell_illidari_council_reflective_shield',
'spell_illidari_dampen_magic');
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(41499,'spell_illidari_council_empyreal_balance'),
(41333,'spell_illidari_council_empyreal_equivalency'),
(41341,'spell_illidari_council_balance_of_power'),
(41480,'spell_illidari_council_deadly_strike'),
(41485,'spell_illidari_council_deadly_poison'),
(41467,'spell_illidari_council_judgement'),
(41469,'spell_illidari_council_seal'),
(41459,'spell_illidari_council_seal'),
(41475,'spell_illidari_council_reflective_shield'),
(41478,'spell_illidari_dampen_magic');
DELETE FROM `creature_text` WHERE `CreatureID` IN(22951,22949,22950,22952) AND (`GroupID` IN(3,4,5,6) OR (`GroupID`=2 AND `ID`=1));
INSERT INTO `creature_text` (`CreatureID`,`GroupID`,`ID`,`Text`,`Type`,`Language`,`Probability`,`Emote`,`Duration`,`Sound`,`BroadcastTextId`,`TextRange`,`Comment`) VALUES
(22949,2,1,'You are MINE!',14,0,100,0,0,11427,21739,0,'council gath SPECIAL2'),
(22949,3,0,'Selama am\'oronor!',14,0,100,0,0,11423,21735,0,'council gath SLAY'),
(22949,4,0,'Well done!',14,0,100,0,0,11424,21736,0,'council gath SLAY_COMT'),
(22949,5,0,'Lord Illidan, I...',14,0,100,0,0,11425,21737,0,'council gath DEATH'),
(22951,2,1,'I\'m full of surprises!',14,0,100,0,0,11487,21719,0,'council mala SPECIAL2'),
(22951,3,0,'My work is done.',14,0,100,0,0,11483,21712,0,'council mala SLAY'),
(22951,4,0,'As it should be.',14,0,100,0,0,11484,21713,0,'council mala SLAY_COMT'),
(22951,5,0,'Destiny... awaits.',14,0,100,0,0,11485,21715,0,'council mala DEATH'),
(22950,2,1,'Sha\'amoor ara mashal?',14,0,100,0,0,11445,21731,0,'council zere SPECIAL2'),
(22950,3,0,'Shorel\'aran.',14,0,100,0,0,11441,21725,0,'council zere SLAY'),
(22950,4,0,'Belesa menoor!',14,0,100,0,0,11442,21727,0,'council zere SLAY_COMT'),
(22950,5,0,'Diel ma\'ahn... orindel\'o.',14,0,100,0,0,11443,21729,0,'council zere DEATH'),
(22952,2,1,'Anar\'alah belore!',14,0,100,0,0,11529,21705,0,'council vera SPECIAL2'),
(22952,3,0,'Valiant effort.',14,0,100,0,0,11525,21699,0,'council vera SLAY'),
(22952,4,0,'A glorious kill!',14,0,100,0,0,11526,21701,0,'council vera SLAY_COMT'),
(22952,5,0,'You got... lucky.',14,0,100,0,0,11527,21703,0,'council vera DEATH');

View File

@@ -2674,8 +2674,11 @@ void SpellMgr::LoadSpellInfoCorrections()
const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->SpellClassMask = flag128(685904631, 1151048, 0, 0);
});
// Death and Decay
ApplySpellFix({ 52212 }, [](SpellInfo* spellInfo)
ApplySpellFix({
52212, // Death and Decay
41485, // Deadly Poison - Black Temple
41487 // Envenom - Black Temple
}, [](SpellInfo* spellInfo)
{
spellInfo->AttributesEx6 |= SPELL_ATTR6_CAN_TARGET_INVISIBLE;
});

View File

@@ -0,0 +1,959 @@
/*
* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
#include "black_temple.h"
#include "GridNotifiers.h"
#include "PassiveAI.h"
#include "InstanceScript.h"
enum Says
{
SAY_COUNCIL_AGRO = 0,
SAY_COUNCIL_ENRAGE = 1,
SAY_COUNCIL_SPECIAL = 2,
SAY_COUNCIL_SLAY = 3,
SAY_COUNCIL_COMNT = 4,
SAY_COUNCIL_DEATH = 5
};
enum Spells
{
// Illidari Council (Trigger)
SPELL_EMPYREAL_BALANCE = 41499,
SPELL_EMPYREAL_EQUIVALENCY = 41333,
// Generic
SPELL_SHARED_RULE = 41342,
SPELL_BERSERK = 45078,
SPELL_BALANCE_OF_POWER = 41341,
SPELL_QUIET_SUICIDE = 3617, // Serverside spell
// High Nethermancer Zerevor's
SPELL_FLAMESTRIKE = 41481,
SPELL_BLIZZARD = 41482,
SPELL_ARCANE_BOLT = 41483,
SPELL_ARCANE_EXPLOSION = 41524,
SPELL_DAMPEN_MAGIC = 41478,
// Lady Malande's
SPELL_EMPOWERED_SMITE = 41471,
SPELL_CIRCLE_OF_HEALING = 41455,
SPELL_REFLECTIVE_SHIELD = 41475,
SPELL_REFLECTIVE_SHIELD_DAMAGE = 33619,
SPELL_DIVINE_WRATH = 41472,
// Gathios the Shatterer's
SPELL_BLESS_PROTECTION = 41450,
SPELL_BLESS_SPELL_WARDING = 41451,
SPELL_CONSECRATION = 41541,
SPELL_HAMMER_OF_JUSTICE = 41468,
SPELL_SEAL_OF_COMMAND = 41469,
SPELL_SEAL_OF_BLOOD = 41459,
SPELL_CHROMATIC_AURA = 41453,
SPELL_DEVOTION_AURA = 41452,
SPELL_JUDGEMENT_PRIMER = 41473,
SPELL_JUDGEMENT = 41467,
SPELL_JUDGEMENT_OF_COMMAND = 41470,
SPELL_JUDGEMENT_OF_BLOOD = 41461,
// Veras Darkshadow's
SPELL_DEADLY_STRIKE = 41480,
SPELL_DEADLY_POISON = 41485,
SPELL_ENVENOM = 41487,
SPELL_VANISH = 41476,
// Veras Vanish Effect
SPELL_BIRTH = 40031,
SPELL_ENVENOM_DUMMY = 41510
};
enum IllidariEvents
{
EVENT_EMPYREAL_EQUIVALENCY = 1,
EVENT_VANISH,
EVENT_DEADLY_STRIKE,
EVENT_FLAMESTRIKE,
EVENT_BLIZZARD,
EVENT_ARCANE_EXPLOSION,
EVENT_ARCANE_EXPLOSION_CHECK,
EVENT_DAMPEN_MAGIC,
EVENT_BLESS,
EVENT_CONSECRATION,
EVENT_AURA,
EVENT_JUDGEMENT,
EVENT_HAMMER_OF_JUSTICE,
EVENT_CIRCLE_OF_HEALING,
EVENT_REFLECTIVE_SHIELD,
EVENT_DIVINE_WRATH,
EVENT_BERSERK
};
enum IllidariMisc
{
SUMMON_COUNCIL_GROUP = 1,
ACTION_REFRESH_DAMPEN
};
uint32 const CouncilData[4] =
{
DATA_GATHIOS_THE_SHATTERER,
DATA_HIGH_NETHERMANCER_ZEREVOR,
DATA_LADY_MALANDE,
DATA_VERAS_DARKSHADOW
};
static uint32 GetRandomBossExcept(uint32 exception)
{
std::vector<uint32> bossData;
for (uint32 data : CouncilData)
if (data != exception)
bossData.emplace_back(data);
return bossData[urand(0, 3)];
}
class boss_illidari_council : public CreatureScript
{
public:
boss_illidari_council() : CreatureScript("boss_illidari_council") { }
struct boss_illidari_councilAI : public BossAI
{
boss_illidari_councilAI(Creature* creature) : BossAI(creature, DATA_ILLIDARI_COUNCIL), _inCombat(false) { }
void Reset() override
{
_Reset();
_inCombat = false;
me->SummonCreatureGroup(SUMMON_COUNCIL_GROUP);
DoCastSelf(SPELL_EMPYREAL_BALANCE, true);
}
void EnterCombat(Unit* /*who*/) override
{
if (!_inCombat)
{
_inCombat = true;
_EnterCombat();
for (uint32 bossData : CouncilData)
{
if (Creature* council = instance->GetCreature(bossData))
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, council);
DoZoneInCombat(council);
}
}
events.ScheduleEvent(EVENT_EMPYREAL_EQUIVALENCY, Seconds(2));
events.ScheduleEvent(EVENT_BERSERK, Minutes(15));
if (Creature* council = instance->GetCreature(CouncilData[urand(0, 3)]))
council->AI()->Talk(SAY_COUNCIL_AGRO);
}
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
if (!me->IsInEvadeMode())
{
_inCombat = false;
for (uint32 bossData : CouncilData)
if (Creature* council = instance->GetCreature(bossData))
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, council);
summons.DespawnAll();
_DespawnAtEvade();
}
}
void JustDied(Unit* /*killer*/) override
{
_inCombat = false;
events.Reset();
instance->SetBossState(DATA_ILLIDARI_COUNCIL, DONE);
for (uint32 bossData : CouncilData)
{
if (Creature* council = instance->GetCreature(bossData))
{
// Allow loot
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, council);
council->LowerPlayerDamageReq(council->GetMaxHealth());
council->CastSpell(council, SPELL_QUIET_SUICIDE, true);
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_EMPYREAL_EQUIVALENCY:
DoCastSelf(SPELL_EMPYREAL_EQUIVALENCY, true);
events.Repeat(Seconds(2));
break;
case EVENT_BERSERK:
for (uint32 bossData : CouncilData)
{
if (Creature* council = instance->GetCreature(bossData))
{
council->CastSpell(council, SPELL_BERSERK, true);
council->AI()->Talk(SAY_COUNCIL_ENRAGE);
}
}
break;
default:
break;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
}
private:
bool _inCombat;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetBlackTempleAI<boss_illidari_councilAI>(creature);
}
};
struct IllidariCouncilBossAI : public BossAI
{
IllidariCouncilBossAI(Creature* creature, uint32 bossId) : BossAI(creature, bossId), _bossId(bossId)
{
SetBoundary(instance->GetBossBoundary(DATA_ILLIDARI_COUNCIL));
}
void Reset() override
{
me->SetCombatPulseDelay(0);
events.Reset();
}
void EnterCombat(Unit* /*who*/) override
{
me->SetCombatPulseDelay(5);
me->setActive(true);
if (Creature* illidari = instance->GetCreature(DATA_ILLIDARI_COUNCIL))
DoZoneInCombat(illidari);
ScheduleTasks();
}
virtual void ScheduleTasks() = 0;
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_COUNCIL_DEATH);
}
void EnterEvadeMode(EvadeReason why) override
{
if (Creature* illidari = instance->GetCreature(DATA_ILLIDARI_COUNCIL))
illidari->AI()->EnterEvadeMode(why);
}
void DamageTaken(Unit* who, uint32 &damage) override
{
if (damage >= me->GetHealth() && who->GetGUID() != me->GetGUID())
damage = me->GetHealth() - 1;
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_COUNCIL_SLAY);
if (roll_chance_i(30))
if (Creature* boss = instance->GetCreature(GetRandomBossExcept(_bossId)))
boss->AI()->Talk(SAY_COUNCIL_COMNT);
}
private:
uint32 _bossId;
};
class HammerTargetSelector : public std::unary_function<Unit*, bool>
{
public:
HammerTargetSelector(Unit const* unit) : _me(unit) { }
bool operator()(Unit* unit) const
{
return _me->IsInRange(unit, 10.0f, 40.0f);
}
private:
Unit const* _me;
};
class boss_gathios_the_shatterer : public CreatureScript
{
public:
boss_gathios_the_shatterer() : CreatureScript("boss_gathios_the_shatterer") { }
struct boss_gathios_the_shattererAI : public IllidariCouncilBossAI
{
boss_gathios_the_shattererAI(Creature* creature) : IllidariCouncilBossAI(creature, DATA_GATHIOS_THE_SHATTERER) { }
void ScheduleTasks() override
{
DoCastSelf(SPELL_SEAL_OF_BLOOD);
events.ScheduleEvent(EVENT_BLESS, Seconds(20));
events.ScheduleEvent(EVENT_CONSECRATION, Seconds(10));
events.ScheduleEvent(EVENT_HAMMER_OF_JUSTICE, Seconds(10));
events.ScheduleEvent(EVENT_JUDGEMENT, Seconds(15));
events.ScheduleEvent(EVENT_AURA, Seconds(6));
}
void ExecuteEvent(uint32 eventId) override
{
switch (eventId)
{
case EVENT_BLESS:
{
std::list<Unit*> TargetList;
Trinity::AnyFriendlyUnitInObjectRangeCheck checker(me, me, 100.0f);
Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(me, TargetList, checker);
Cell::VisitAllObjects(me, searcher, 100.0f);
if (!TargetList.empty())
{
Unit* target = Trinity::Containers::SelectRandomContainerElement(TargetList);
DoCast(target, RAND(SPELL_BLESS_PROTECTION, SPELL_BLESS_SPELL_WARDING));
}
events.Repeat(Seconds(30), Seconds(45));
break;
}
case EVENT_AURA:
DoCastSelf(RAND(SPELL_CHROMATIC_AURA, SPELL_DEVOTION_AURA));
events.Repeat(Seconds(30));
break;
case EVENT_HAMMER_OF_JUSTICE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, HammerTargetSelector(me)))
DoCast(target, SPELL_HAMMER_OF_JUSTICE);
events.Repeat(Seconds(20));
break;
case EVENT_JUDGEMENT:
DoCastVictim(SPELL_JUDGEMENT);
events.Repeat(Seconds(15));
break;
case EVENT_CONSECRATION:
DoCastSelf(SPELL_CONSECRATION);
events.Repeat(Seconds(30), Seconds(35));
break;
default:
break;
}
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetBlackTempleAI<boss_gathios_the_shattererAI>(creature);
}
};
class boss_high_nethermancer_zerevor : public CreatureScript
{
public:
boss_high_nethermancer_zerevor() : CreatureScript("boss_high_nethermancer_zerevor") { }
struct boss_high_nethermancer_zerevorAI : public IllidariCouncilBossAI
{
boss_high_nethermancer_zerevorAI(Creature* creature) : IllidariCouncilBossAI(creature, DATA_HIGH_NETHERMANCER_ZEREVOR), _canUseArcaneExplosion(true) { }
void Reset() override
{
IllidariCouncilBossAI::Reset();
_canUseArcaneExplosion = true;
DoCastSelf(SPELL_DAMPEN_MAGIC);
}
void ScheduleTasks() override
{
events.ScheduleEvent(EVENT_FLAMESTRIKE, Seconds(8));
events.ScheduleEvent(EVENT_BLIZZARD, Seconds(25));
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, Seconds(5));
DoCastSelf(SPELL_DAMPEN_MAGIC);
}
void DoAction(int32 actionId) override
{
if (actionId == ACTION_REFRESH_DAMPEN)
events.ScheduleEvent(EVENT_DAMPEN_MAGIC, Seconds(50));
}
void ExecuteEvent(uint32 eventId) override
{
switch (eventId)
{
case EVENT_FLAMESTRIKE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_FLAMESTRIKE);
Talk(SAY_COUNCIL_SPECIAL);
events.Repeat(Seconds(40));
break;
case EVENT_BLIZZARD:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_BLIZZARD);
events.Repeat(Seconds(15), Seconds(40));
break;
case EVENT_ARCANE_EXPLOSION_CHECK:
_canUseArcaneExplosion = true;
break;
case EVENT_ARCANE_EXPLOSION:
if (_canUseArcaneExplosion && SelectTarget(SELECT_TARGET_RANDOM, 0, 10.0f))
{
DoCastSelf(SPELL_ARCANE_EXPLOSION);
_canUseArcaneExplosion = false;
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION_CHECK, Seconds(5));
}
events.Repeat(Seconds(1));
break;
case EVENT_DAMPEN_MAGIC:
DoCastSelf(SPELL_DAMPEN_MAGIC);
break;
default:
break;
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
ExecuteEvent(eventId);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoSpellAttackIfReady(SPELL_ARCANE_BOLT);
}
private:
bool _canUseArcaneExplosion;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetBlackTempleAI<boss_high_nethermancer_zerevorAI>(creature);
}
};
class boss_lady_malande : public CreatureScript
{
public:
boss_lady_malande() : CreatureScript("boss_lady_malande") { }
struct boss_lady_malandeAI : public IllidariCouncilBossAI
{
boss_lady_malandeAI(Creature* creature) : IllidariCouncilBossAI(creature, DATA_LADY_MALANDE) { }
void ScheduleTasks() override
{
events.ScheduleEvent(EVENT_CIRCLE_OF_HEALING, Seconds(20));
events.ScheduleEvent(EVENT_REFLECTIVE_SHIELD, Seconds(25));
events.ScheduleEvent(EVENT_DIVINE_WRATH, Seconds(32));
}
void HealReceived(Unit* /*who*/, uint32& addhealth) override
{
// Need be negative to heal trigger
int32 bp = addhealth * (-1);
me->CastCustomSpell(SPELL_SHARED_RULE, SPELLVALUE_BASE_POINT0, bp, (Unit*) nullptr, true);
}
void ExecuteEvent(uint32 eventId) override
{
switch (eventId)
{
case EVENT_CIRCLE_OF_HEALING:
DoCastSelf(SPELL_CIRCLE_OF_HEALING);
events.Repeat(Seconds(20), Seconds(35));
break;
case EVENT_REFLECTIVE_SHIELD:
DoCastSelf(SPELL_REFLECTIVE_SHIELD);
Talk(SAY_COUNCIL_SPECIAL);
events.Repeat(Seconds(40));
break;
case EVENT_DIVINE_WRATH:
DoCastVictim(SPELL_DIVINE_WRATH);
events.Repeat(Seconds(20));
break;
default:
break;
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
ExecuteEvent(eventId);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoSpellAttackIfReady(SPELL_EMPOWERED_SMITE);
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetBlackTempleAI<boss_lady_malandeAI>(creature);
}
};
class boss_veras_darkshadow : public CreatureScript
{
public:
boss_veras_darkshadow() : CreatureScript("boss_veras_darkshadow") { }
struct boss_veras_darkshadowAI : public IllidariCouncilBossAI
{
boss_veras_darkshadowAI(Creature* creature) : IllidariCouncilBossAI(creature, DATA_VERAS_DARKSHADOW)
{
me->SetMaxHealth(1327900);
me->SetFullHealth();
}
void ScheduleTasks() override
{
events.ScheduleEvent(EVENT_DEADLY_STRIKE, Seconds(18));
events.ScheduleEvent(EVENT_VANISH, Seconds(18));
}
void ExecuteEvent(uint32 eventId) override
{
switch (eventId)
{
case EVENT_DEADLY_STRIKE:
DoCastSelf(SPELL_DEADLY_STRIKE);
events.Repeat(Seconds(60));
break;
case EVENT_VANISH:
DoCastSelf(SPELL_VANISH);
Talk(SAY_COUNCIL_SPECIAL);
events.Repeat(Seconds(60));
break;
default:
break;
}
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetBlackTempleAI<boss_veras_darkshadowAI>(creature);
}
};
class npc_veras_vanish_effect : public CreatureScript
{
public:
npc_veras_vanish_effect() : CreatureScript("npc_veras_vanish_effect") { }
struct npc_veras_vanish_effectAI : public PassiveAI
{
npc_veras_vanish_effectAI(Creature* creature) : PassiveAI(creature) { }
void Reset() override
{
DoCastSelf(SPELL_BIRTH, true);
DoCastSelf(SPELL_ENVENOM_DUMMY, true);
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetBlackTempleAI<npc_veras_vanish_effectAI>(creature);
}
};
// 41499 - Empyreal Balance
class spell_illidari_council_empyreal_balance : public SpellScriptLoader
{
public:
spell_illidari_council_empyreal_balance() : SpellScriptLoader("spell_illidari_council_empyreal_balance") { }
class spell_illidari_council_empyreal_balance_SpellScript : public SpellScript
{
PrepareSpellScript(spell_illidari_council_empyreal_balance_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_BALANCE_OF_POWER });
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
Unit* target = GetHitUnit();
target->CastSpell(target, SPELL_BALANCE_OF_POWER, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_illidari_council_empyreal_balance_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_illidari_council_empyreal_balance_SpellScript();
}
};
// 41333 - Empyreal Equivalency
class spell_illidari_council_empyreal_equivalency : public SpellScriptLoader
{
public:
spell_illidari_council_empyreal_equivalency() : SpellScriptLoader("spell_illidari_council_empyreal_equivalency") { }
class spell_illidari_council_empyreal_equivalency_SpellScript : public SpellScript
{
PrepareSpellScript(spell_illidari_council_empyreal_equivalency_SpellScript);
void HandleScript(SpellEffIndex /*effIndex*/)
{
Unit* target = GetHitUnit();
int32 casterHpPct = (int32) GetCaster()->GetHealthPct();
uint32 newHp = target->CountPctFromMaxHealth(casterHpPct);
if (newHp <= 0)
newHp = target->GetMaxHealth() - 1;
target->SetHealth(newHp);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_illidari_council_empyreal_equivalency_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_illidari_council_empyreal_equivalency_SpellScript();
}
};
// 41341 - Balance of Power
class spell_illidari_council_balance_of_power : public SpellScriptLoader
{
public:
spell_illidari_council_balance_of_power() : SpellScriptLoader("spell_illidari_council_balance_of_power") { }
class spell_illidari_council_balance_of_power_AuraScript : public AuraScript
{
PrepareAuraScript(spell_illidari_council_balance_of_power_AuraScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_SHARED_RULE });
}
void Absorb(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& /*absorbAmount*/)
{
PreventDefaultAction();
int32 bp = dmgInfo.GetDamage();
GetTarget()->CastCustomSpell(SPELL_SHARED_RULE, SPELLVALUE_BASE_POINT0, bp, (Unit*) nullptr, true, nullptr, aurEff);
}
void Register() override
{
OnEffectAbsorb += AuraEffectAbsorbFn(spell_illidari_council_balance_of_power_AuraScript::Absorb, EFFECT_0);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_illidari_council_balance_of_power_AuraScript();
}
};
// 41480 - Deadly Strike
class spell_illidari_council_deadly_strike : public SpellScriptLoader
{
public:
spell_illidari_council_deadly_strike() : SpellScriptLoader("spell_illidari_council_deadly_strike") { }
class spell_illidari_council_deadly_strike_AuraScript : public AuraScript
{
PrepareAuraScript(spell_illidari_council_deadly_strike_AuraScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DEADLY_POISON });
}
void OnTrigger(AuraEffect const* aurEff)
{
PreventDefaultAction();
if (Unit* victim = GetTarget()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0))
GetTarget()->CastSpell(victim, SPELL_DEADLY_POISON, true, nullptr, aurEff);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidari_council_deadly_strike_AuraScript::OnTrigger, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_illidari_council_deadly_strike_AuraScript();
}
};
// 41485 - Deadly Poison
class spell_illidari_council_deadly_poison : public SpellScriptLoader
{
public:
spell_illidari_council_deadly_poison() : SpellScriptLoader("spell_illidari_council_deadly_poison") { }
class spell_illidari_council_deadly_poison_AuraScript : public AuraScript
{
PrepareAuraScript(spell_illidari_council_deadly_poison_AuraScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_ENVENOM });
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* caster = GetCaster())
caster->CastSpell(GetTarget(), SPELL_ENVENOM, true);
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_illidari_council_deadly_poison_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_illidari_council_deadly_poison_AuraScript();
}
};
// 41475 - Reflective Shield
class spell_illidari_council_reflective_shield : public SpellScriptLoader
{
public:
spell_illidari_council_reflective_shield() : SpellScriptLoader("spell_illidari_council_reflective_shield") { }
class spell_illidari_council_reflective_shield_AuraScript : public AuraScript
{
PrepareAuraScript(spell_illidari_council_reflective_shield_AuraScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_REFLECTIVE_SHIELD_DAMAGE });
}
void OnAbsorb(AuraEffect* aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
{
Unit* target = GetTarget();
if (dmgInfo.GetAttacker() == target)
return;
int32 bp = absorbAmount / 2;
target->CastCustomSpell(dmgInfo.GetAttacker(), SPELL_REFLECTIVE_SHIELD_DAMAGE, &bp, nullptr, nullptr, true, nullptr, aurEff);
}
void Register() override
{
AfterEffectAbsorb += AuraEffectAbsorbFn(spell_illidari_council_reflective_shield_AuraScript::OnAbsorb, EFFECT_0);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_illidari_council_reflective_shield_AuraScript();
}
};
// 41467 - Judgement
class spell_illidari_council_judgement : public SpellScriptLoader
{
public:
spell_illidari_council_judgement() : SpellScriptLoader("spell_illidari_council_judgement") { }
class spell_illidari_council_judgement_SpellScript : public SpellScript
{
PrepareSpellScript(spell_illidari_council_judgement_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_JUDGEMENT_OF_BLOOD,
SPELL_JUDGEMENT_OF_COMMAND,
SPELL_JUDGEMENT_PRIMER
});
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
Unit* target = GetHitUnit();
uint32 judgementId = caster->HasAura(SPELL_SEAL_OF_BLOOD) ? SPELL_JUDGEMENT_OF_BLOOD : SPELL_JUDGEMENT_OF_COMMAND;
caster->CastSpell(target, SPELL_JUDGEMENT_PRIMER, true);
caster->CastSpell(target, judgementId, true);
}
void OnFinishCast()
{
if (Creature* caster = GetCaster()->ToCreature())
caster->AI()->Talk(SAY_COUNCIL_SPECIAL);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_illidari_council_judgement_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
AfterCast += SpellCastFn(spell_illidari_council_judgement_SpellScript::OnFinishCast);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_illidari_council_judgement_SpellScript();
}
};
/* 41469 - Seal of Command
41459 - Seal of Blood */
class spell_illidari_council_seal : public SpellScriptLoader
{
public:
spell_illidari_council_seal() : SpellScriptLoader("spell_illidari_council_seal") { }
class spell_illidari_council_seal_AuraScript : public AuraScript
{
PrepareAuraScript(spell_illidari_council_seal_AuraScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_SEAL_OF_COMMAND, SPELL_SEAL_OF_BLOOD });
}
void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
if (target->IsInWorld() && target->IsAlive())
{
uint32 spellId = aurEff->GetId() == SPELL_SEAL_OF_COMMAND ? SPELL_SEAL_OF_BLOOD : SPELL_SEAL_OF_COMMAND;
target->CastSpell(target, spellId, true);
}
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_illidari_council_seal_AuraScript::OnRemove, EFFECT_2, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_illidari_council_seal_AuraScript();
}
};
// 41478 - Dampen Magic
class spell_illidari_dampen_magic : public SpellScriptLoader
{
public:
spell_illidari_dampen_magic() : SpellScriptLoader("spell_illidari_dampen_magic") { }
class spell_illidari_dampen_magic_AuraScript : public AuraScript
{
PrepareAuraScript(spell_illidari_dampen_magic_AuraScript);
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Creature* target = GetTarget()->ToCreature())
{
AuraRemoveMode mode = GetTargetApplication()->GetRemoveMode();
if (mode == AURA_REMOVE_BY_ENEMY_SPELL || mode == AURA_REMOVE_BY_EXPIRE)
target->AI()->DoAction(ACTION_REFRESH_DAMPEN);
}
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_illidari_dampen_magic_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_illidari_dampen_magic_AuraScript();
}
};
void AddSC_boss_illidari_council()
{
new boss_illidari_council();
new boss_gathios_the_shatterer();
new boss_lady_malande();
new boss_veras_darkshadow();
new boss_high_nethermancer_zerevor();
new npc_veras_vanish_effect();
new spell_illidari_council_empyreal_balance();
new spell_illidari_council_empyreal_equivalency();
new spell_illidari_council_balance_of_power();
new spell_illidari_council_deadly_strike();
new spell_illidari_council_deadly_poison();
new spell_illidari_council_reflective_shield();
new spell_illidari_council_judgement();
new spell_illidari_council_seal();
new spell_illidari_dampen_magic();
}

View File

@@ -1,950 +0,0 @@
/*
* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
* Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: Illidari_Council
SD%Complete: 95
SDComment: Circle of Healing not working properly.
SDCategory: Black Temple
EndScriptData */
#include "ScriptMgr.h"
#include "black_temple.h"
#include "InstanceScript.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
enum IllidariCouncil
{
//Speech'n'Sounds
SAY_GATH_SPECIAL1 = 2,
SAY_GATH_SPECIAL2 = 3,
SAY_GATH_SLAY = 4,
SAY_GATH_COMNT = 5,
SAY_GATH_DEATH = 6,
SAY_MALA_SPECIAL1 = 2,
SAY_MALA_SPECIAL2 = 3,
SAY_MALA_SLAY = 4,
SAY_MALA_COMNT = 5,
SAY_MALA_DEATH = 6,
SAY_ZERE_SPECIAL1 = 2,
SAY_ZERE_SPECIAL2 = 3,
SAY_ZERE_SLAY = 4,
SAY_ZERE_COMNT = 5,
SAY_ZERE_DEATH = 6,
SAY_VERA_SPECIAL1 = 2,
SAY_VERA_SPECIAL2 = 3,
SAY_VERA_SLAY = 4,
SAY_VERA_COMNT = 5,
SAY_VERA_DEATH = 6,
AKAMAID = 23089,
// High Nethermancer Zerevor's spells
SPELL_FLAMESTRIKE = 41481,
SPELL_BLIZZARD = 41482,
SPELL_ARCANE_BOLT = 41483,
SPELL_ARCANE_EXPLOSION = 41524,
SPELL_DAMPEN_MAGIC = 41478,
// Lady Malande's spells
SPELL_EMPOWERED_SMITE = 41471,
SPELL_CIRCLE_OF_HEALING = 41455,
SPELL_REFLECTIVE_SHIELD = 41475,
SPELL_REFLECTIVE_SHIELD_T = 33619,
SPELL_DIVINE_WRATH = 41472,
SPELL_HEAL_VISUAL = 24171,
// Gathios the Shatterer's spells
SPELL_BLESS_PROTECTION = 41450,
SPELL_BLESS_SPELLWARD = 41451,
SPELL_CONSECRATION = 41541,
SPELL_HAMMER_OF_JUSTICE = 41468,
SPELL_SEAL_OF_COMMAND = 41469,
SPELL_SEAL_OF_BLOOD = 41459,
SPELL_CHROMATIC_AURA = 41453,
SPELL_DEVOTION_AURA = 41452,
// Veras Darkshadow's spells
SPELL_DEADLY_POISON = 41485,
SPELL_ENVENOM = 41487,
SPELL_VANISH = 41479,
SPELL_BERSERK = 45078
};
struct CouncilYells
{
int32 entry;
uint32 timer;
};
static CouncilYells CouncilAggro[]=
{
{0, 5000}, // Gathios
{0, 5500}, // Veras
{0, 5000}, // Malande
{0, 0}, // Zerevor
};
// Need to get proper timers for this later
static CouncilYells CouncilEnrage[]=
{
{1, 2000}, // Gathios
{1, 6000}, // Veras
{1, 5000}, // Malande
{1, 0}, // Zerevor
};
class npc_blood_elf_council_voice_trigger : public CreatureScript
{
public:
npc_blood_elf_council_voice_trigger() : CreatureScript("npc_blood_elf_council_voice_trigger") { }
CreatureAI* GetAI(Creature* c) const override
{
return GetBlackTempleAI<npc_blood_elf_council_voice_triggerAI>(c);
}
struct npc_blood_elf_council_voice_triggerAI : public ScriptedAI
{
npc_blood_elf_council_voice_triggerAI(Creature* creature) : ScriptedAI(creature)
{
Initialize();
}
void Initialize()
{
EnrageTimer = 900000; // 15 minutes
AggroYellTimer = 500;
YellCounter = 0;
EventStarted = false;
}
ObjectGuid Council[4];
uint32 EnrageTimer;
uint32 AggroYellTimer;
uint8 YellCounter; // Serves as the counter for both the aggro and enrage yells
bool EventStarted;
void Reset() override
{
Initialize();
}
// finds and stores the GUIDs for each Council member using instance data system.
void LoadCouncilGUIDs()
{
if (InstanceScript* instance = me->GetInstanceScript())
{
Council[0] = instance->GetGuidData(DATA_GATHIOS_THE_SHATTERER);
Council[1] = instance->GetGuidData(DATA_VERAS_DARKSHADOW);
Council[2] = instance->GetGuidData(DATA_LADY_MALANDE);
Council[3] = instance->GetGuidData(DATA_HIGH_NETHERMANCER_ZEREVOR);
}
}
void EnterCombat(Unit* /*who*/) override { }
void AttackStart(Unit* /*who*/) override { }
void MoveInLineOfSight(Unit* /*who*/) override { }
void UpdateAI(uint32 diff) override
{
if (!EventStarted)
return;
if (YellCounter > 3)
return;
if (AggroYellTimer)
{
if (AggroYellTimer <= diff)
{
if (Creature* pMember = ObjectAccessor::GetCreature(*me, Council[YellCounter]))
{
pMember->AI()->Talk(CouncilAggro[YellCounter].entry);
AggroYellTimer = CouncilAggro[YellCounter].timer;
}
++YellCounter;
if (YellCounter > 3)
YellCounter = 0; // Reuse for Enrage Yells
} else AggroYellTimer -= diff;
}
if (EnrageTimer)
{
if (EnrageTimer <= diff)
{
if (Creature* pMember = ObjectAccessor::GetCreature(*me, Council[YellCounter]))
{
pMember->CastSpell(pMember, SPELL_BERSERK, true);
pMember->AI()->Talk(CouncilEnrage[YellCounter].entry);
EnrageTimer = CouncilEnrage[YellCounter].timer;
}
++YellCounter;
} else EnrageTimer -= diff;
}
}
};
};
class npc_illidari_council : public CreatureScript
{
public:
npc_illidari_council() : CreatureScript("npc_illidari_council") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetBlackTempleAI<npc_illidari_councilAI>(creature);
}
struct npc_illidari_councilAI : public ScriptedAI
{
npc_illidari_councilAI(Creature* creature) : ScriptedAI(creature)
{
Initialize();
instance = creature->GetInstanceScript();
SetBoundary(instance->GetBossBoundary(DATA_ILLIDARI_COUNCIL));
}
void Initialize()
{
CheckTimer = 2000;
EndEventTimer = 0;
DeathCount = 0;
EventBegun = false;
}
InstanceScript* instance;
ObjectGuid Council[4];
uint32 CheckTimer;
uint32 EndEventTimer;
uint8 DeathCount;
bool EventBegun;
void Reset() override
{
Initialize();
Creature* pMember = nullptr;
for (uint8 i = 0; i < 4; ++i)
{
pMember = ObjectAccessor::GetCreature((*me), Council[i]);
if (!pMember)
continue;
if (!pMember->IsAlive())
{
pMember->RemoveCorpse();
pMember->Respawn();
}
pMember->AI()->EnterEvadeMode();
}
instance->SetBossState(DATA_ILLIDARI_COUNCIL, NOT_STARTED);
if (Creature* VoiceTrigger = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLOOD_ELF_COUNCIL_VOICE)))
VoiceTrigger->AI()->EnterEvadeMode();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->SetDisplayId(11686);
}
void EnterCombat(Unit* /*who*/) override { }
void AttackStart(Unit* /*who*/) override { }
void MoveInLineOfSight(Unit* /*who*/) override { }
void StartEvent(Unit* target)
{
if (target && target->IsAlive())
{
Council[0] = instance->GetGuidData(DATA_GATHIOS_THE_SHATTERER);
Council[1] = instance->GetGuidData(DATA_HIGH_NETHERMANCER_ZEREVOR);
Council[2] = instance->GetGuidData(DATA_LADY_MALANDE);
Council[3] = instance->GetGuidData(DATA_VERAS_DARKSHADOW);
// Start the event for the Voice Trigger
if (Creature* VoiceTrigger = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLOOD_ELF_COUNCIL_VOICE)))
{
ENSURE_AI(npc_blood_elf_council_voice_trigger::npc_blood_elf_council_voice_triggerAI, VoiceTrigger->AI())->LoadCouncilGUIDs();
ENSURE_AI(npc_blood_elf_council_voice_trigger::npc_blood_elf_council_voice_triggerAI, VoiceTrigger->AI())->EventStarted = true;
}
for (uint8 i = 0; i < 4; ++i)
{
if (!Council[i].IsEmpty())
{
if (Creature* member = ObjectAccessor::GetCreature(*me, Council[i]))
if (member->IsAlive())
member->AI()->AttackStart(target);
}
}
instance->SetBossState(DATA_ILLIDARI_COUNCIL, IN_PROGRESS);
EventBegun = true;
}
}
void UpdateAI(uint32 diff) override
{
if (!EventBegun)
return;
if (EndEventTimer)
{
if (EndEventTimer <= diff)
{
if (DeathCount > 3)
{
if (Creature* VoiceTrigger = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLOOD_ELF_COUNCIL_VOICE)))
VoiceTrigger->DealDamage(VoiceTrigger, VoiceTrigger->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
instance->SetBossState(DATA_ILLIDARI_COUNCIL, DONE);
//me->SummonCreature(AKAMAID, 746.466980f, 304.394989f, 311.90208f, 6.272870f, TEMPSUMMON_DEAD_DESPAWN, 0);
me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
return;
}
Creature* pMember = (ObjectAccessor::GetCreature(*me, Council[DeathCount]));
if (pMember && pMember->IsAlive())
pMember->DealDamage(pMember, pMember->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
++DeathCount;
EndEventTimer = 1500;
} else EndEventTimer -= diff;
}
if (CheckTimer)
{
if (CheckTimer <= diff)
{
uint8 EvadeCheck = 0;
for (uint8 i = 0; i < 4; ++i)
{
if (!Council[i].IsEmpty())
{
if (Creature* Member = (ObjectAccessor::GetCreature((*me), Council[i])))
{
// This is the evade/death check.
if (Member->IsAlive() && !Member->GetVictim())
++EvadeCheck; //If all members evade, we reset so that players can properly reset the event
else if (!Member->IsAlive()) // If even one member dies, kill the rest, set instance data, and kill self.
{
EndEventTimer = 1000;
CheckTimer = 0;
return;
}
}
}
}
if (EvadeCheck > 3)
Reset();
CheckTimer = 2000;
} else CheckTimer -= diff;
}
}
};
};
struct boss_illidari_councilAI : public ScriptedAI
{
boss_illidari_councilAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
LoadedGUIDs = false;
}
ObjectGuid Council[4];
InstanceScript* instance;
bool LoadedGUIDs;
void EnterCombat(Unit* who) override
{
if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ILLIDARI_COUNCIL)))
ENSURE_AI(npc_illidari_council::npc_illidari_councilAI, controller->AI())->StartEvent(who);
DoZoneInCombat();
// Load GUIDs on first aggro because the Creature guids are only set as the creatures are created in world-
// this means that for each creature, it will attempt to LoadGUIDs even though some of the other creatures are
// not in world, and thus have no GUID set in the instance data system. Putting it in aggro ensures that all the creatures
// have been loaded and have their GUIDs set in the instance data system.
if (!LoadedGUIDs)
LoadGUIDs();
}
void EnterEvadeMode(EvadeReason why) override
{
for (uint8 i = 0; i < 4; ++i)
{
if (Unit* unit = ObjectAccessor::GetUnit(*me, Council[i]))
if (unit != me && unit->GetVictim())
{
AttackStart(unit->GetVictim());
return;
}
}
ScriptedAI::EnterEvadeMode(why);
}
void DamageTaken(Unit* done_by, uint32 &damage) override
{
if (done_by == me)
return;
damage /= 4;
for (uint8 i = 0; i < 4; ++i)
{
if (Creature* unit = ObjectAccessor::GetCreature(*me, Council[i]))
if (unit != me && damage < unit->GetHealth())
{
unit->ModifyHealth(-int32(damage));
unit->LowerPlayerDamageReq(damage);
}
}
}
void LoadGUIDs()
{
Council[0] = instance->GetGuidData(DATA_LADY_MALANDE);
Council[1] = instance->GetGuidData(DATA_HIGH_NETHERMANCER_ZEREVOR);
Council[2] = instance->GetGuidData(DATA_GATHIOS_THE_SHATTERER);
Council[3] = instance->GetGuidData(DATA_VERAS_DARKSHADOW);
LoadedGUIDs = true;
}
};
class boss_gathios_the_shatterer : public CreatureScript
{
public:
boss_gathios_the_shatterer() : CreatureScript("boss_gathios_the_shatterer") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetBlackTempleAI<boss_gathios_the_shattererAI>(creature);
}
struct boss_gathios_the_shattererAI : public boss_illidari_councilAI
{
boss_gathios_the_shattererAI(Creature* creature) : boss_illidari_councilAI(creature)
{
Initialize();
}
void Initialize()
{
ConsecrationTimer = 40000;
HammerOfJusticeTimer = 10000;
SealTimer = 40000;
AuraTimer = 90000;
BlessingTimer = 60000;
}
uint32 ConsecrationTimer;
uint32 HammerOfJusticeTimer;
uint32 SealTimer;
uint32 AuraTimer;
uint32 BlessingTimer;
void Reset() override
{
Initialize();
}
void KilledUnit(Unit* /*victim*/) override
{
Talk(SAY_GATH_SLAY);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_GATH_DEATH);
}
Unit* SelectCouncilMember()
{
Unit* unit = me;
uint32 member = 0; // He chooses Lady Malande most often
if (rand32() % 10 == 0) // But there is a chance he picks someone else.
member = urand(1, 3);
if (member != 2) // No need to create another pointer to us using Unit::GetUnit
unit = ObjectAccessor::GetUnit(*me, Council[member]);
return unit;
}
void CastAuraOnCouncil()
{
uint32 spellid = 0;
switch (urand(0, 1))
{
case 0: spellid = SPELL_DEVOTION_AURA; break;
case 1: spellid = SPELL_CHROMATIC_AURA; break;
}
for (uint8 i = 0; i < 4; ++i)
{
Unit* unit = ObjectAccessor::GetUnit(*me, Council[i]);
if (unit)
unit->CastSpell(unit, spellid, true, 0, 0, me->GetGUID());
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (BlessingTimer <= diff)
{
if (Unit* unit = SelectCouncilMember())
{
switch (urand(0, 1))
{
case 0:
DoCast(unit, SPELL_BLESS_SPELLWARD);
break;
case 1:
DoCast(unit, SPELL_BLESS_PROTECTION);
break;
}
}
BlessingTimer = 60000;
} else BlessingTimer -= diff;
if (ConsecrationTimer <= diff)
{
DoCast(me, SPELL_CONSECRATION);
ConsecrationTimer = 40000;
} else ConsecrationTimer -= diff;
if (HammerOfJusticeTimer <= diff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
// is in ~10-40 yd range
if (me->IsInRange(target, 10.0f, 40.0f, false))
{
DoCast(target, SPELL_HAMMER_OF_JUSTICE);
HammerOfJusticeTimer = 20000;
}
}
} else HammerOfJusticeTimer -= diff;
if (SealTimer <= diff)
{
switch (urand(0, 1))
{
case 0: DoCast(me, SPELL_SEAL_OF_COMMAND); break;
case 1: DoCast(me, SPELL_SEAL_OF_BLOOD); break;
}
SealTimer = 40000;
} else SealTimer -= diff;
if (AuraTimer <= diff)
{
CastAuraOnCouncil();
AuraTimer = 90000;
} else AuraTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
class boss_high_nethermancer_zerevor : public CreatureScript
{
public:
boss_high_nethermancer_zerevor() : CreatureScript("boss_high_nethermancer_zerevor") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetBlackTempleAI<boss_high_nethermancer_zerevorAI>(creature);
}
struct boss_high_nethermancer_zerevorAI : public boss_illidari_councilAI
{
boss_high_nethermancer_zerevorAI(Creature* creature) : boss_illidari_councilAI(creature)
{
Initialize();
}
void Initialize()
{
BlizzardTimer = urand(30, 91) * 1000;
FlamestrikeTimer = urand(30, 91) * 1000;
ArcaneBoltTimer = 10000;
DampenMagicTimer = 2000;
ArcaneExplosionTimer = 14000;
Cooldown = 0;
}
uint32 BlizzardTimer;
uint32 FlamestrikeTimer;
uint32 ArcaneBoltTimer;
uint32 DampenMagicTimer;
uint32 Cooldown;
uint32 ArcaneExplosionTimer;
void Reset() override
{
Initialize();
}
void KilledUnit(Unit* /*victim*/) override
{
Talk(SAY_ZERE_SLAY);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_ZERE_DEATH);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (Cooldown)
{
if (Cooldown <= diff) Cooldown = 0;
else
{
Cooldown -= diff;
return; // Don't cast any other spells if global cooldown is still ticking
}
}
if (DampenMagicTimer <= diff)
{
DoCast(me, SPELL_DAMPEN_MAGIC);
Cooldown = 1000;
DampenMagicTimer = 67200; // almost 1, 12 minutes
ArcaneBoltTimer += 1000; // Give the Mage some time to spellsteal Dampen.
} else DampenMagicTimer -= diff;
if (ArcaneExplosionTimer <= diff)
{
DoCastVictim(SPELL_ARCANE_EXPLOSION);
Cooldown = 1000;
ArcaneExplosionTimer = 14000;
} else ArcaneExplosionTimer -= diff;
if (ArcaneBoltTimer <= diff)
{
DoCastVictim(SPELL_ARCANE_BOLT);
ArcaneBoltTimer = 3000;
Cooldown = 2000;
} else ArcaneBoltTimer -= diff;
if (BlizzardTimer <= diff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
DoCast(target, SPELL_BLIZZARD);
BlizzardTimer = urand(45, 91) * 1000;
FlamestrikeTimer += 10000;
Cooldown = 1000;
}
} else BlizzardTimer -= diff;
if (FlamestrikeTimer <= diff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
DoCast(target, SPELL_FLAMESTRIKE);
FlamestrikeTimer = urand(55, 101) * 1000;
BlizzardTimer += 10000;
Cooldown = 2000;
}
} else FlamestrikeTimer -= diff;
}
};
};
class boss_lady_malande : public CreatureScript
{
public:
boss_lady_malande() : CreatureScript("boss_lady_malande") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetBlackTempleAI<boss_lady_malandeAI>(creature);
}
struct boss_lady_malandeAI : public boss_illidari_councilAI
{
boss_lady_malandeAI(Creature* creature) : boss_illidari_councilAI(creature)
{
Initialize();
}
void Initialize()
{
EmpoweredSmiteTimer = 38000;
CircleOfHealingTimer = 20000;
DivineWrathTimer = 40000;
ReflectiveShieldTimer = 0;
}
uint32 EmpoweredSmiteTimer;
uint32 CircleOfHealingTimer;
uint32 DivineWrathTimer;
uint32 ReflectiveShieldTimer;
void Reset() override
{
Initialize();
}
void KilledUnit(Unit* /*victim*/) override
{
Talk(SAY_MALA_SLAY);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_MALA_DEATH);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (EmpoweredSmiteTimer <= diff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
DoCast(target, SPELL_EMPOWERED_SMITE);
EmpoweredSmiteTimer = 38000;
}
} else EmpoweredSmiteTimer -= diff;
if (CircleOfHealingTimer <= diff)
{
DoCast(me, SPELL_CIRCLE_OF_HEALING);
CircleOfHealingTimer = 60000;
} else CircleOfHealingTimer -= diff;
if (DivineWrathTimer <= diff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
DoCast(target, SPELL_DIVINE_WRATH);
DivineWrathTimer = urand(40, 81) * 1000;
}
} else DivineWrathTimer -= diff;
if (ReflectiveShieldTimer <= diff)
{
DoCast(me, SPELL_REFLECTIVE_SHIELD);
ReflectiveShieldTimer = 65000;
} else ReflectiveShieldTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
class boss_veras_darkshadow : public CreatureScript
{
public:
boss_veras_darkshadow() : CreatureScript("boss_veras_darkshadow") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetBlackTempleAI<boss_veras_darkshadowAI>(creature);
}
struct boss_veras_darkshadowAI : public boss_illidari_councilAI
{
boss_veras_darkshadowAI(Creature* creature) : boss_illidari_councilAI(creature)
{
Initialize();
}
void Initialize()
{
DeadlyPoisonTimer = 20000;
VanishTimer = urand(60, 121) * 1000;
AppearEnvenomTimer = 150000;
HasVanished = false;
}
uint32 DeadlyPoisonTimer;
uint32 VanishTimer;
uint32 AppearEnvenomTimer;
bool HasVanished;
void Reset() override
{
Initialize();
me->SetVisible(true);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
void KilledUnit(Unit* /*victim*/) override
{
Talk(SAY_VERA_SLAY);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_VERA_DEATH);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (!HasVanished)
{
if (DeadlyPoisonTimer <= diff)
{
DoCastVictim(SPELL_DEADLY_POISON);
DeadlyPoisonTimer = urand(15, 46) * 1000;
} else DeadlyPoisonTimer -= diff;
if (AppearEnvenomTimer <= diff) // Cast Envenom. This is cast 4 seconds after Vanish is over
{
DoCastVictim(SPELL_ENVENOM);
AppearEnvenomTimer = 90000;
} else AppearEnvenomTimer -= diff;
if (VanishTimer <= diff) // Disappear and stop attacking, but follow a random unit
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
VanishTimer = 30000;
AppearEnvenomTimer= 28000;
HasVanished = true;
me->SetVisible(false);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
DoResetThreat();
// Chase a unit. Check before DoMeleeAttackIfReady prevents from attacking
me->AddThreat(target, 500000.0f);
me->GetMotionMaster()->MoveChase(target);
}
} else VanishTimer -= diff;
DoMeleeAttackIfReady();
}
else
{
if (VanishTimer <= diff) // Become attackable and poison current target
{
Unit* target = me->GetVictim();
DoCast(target, SPELL_DEADLY_POISON);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
DoResetThreat();
me->AddThreat(target, 3000.0f); // Make Veras attack his target for a while, he will cast Envenom 4 seconds after.
DeadlyPoisonTimer += 6000;
VanishTimer = 90000;
AppearEnvenomTimer = 4000;
HasVanished = false;
} else VanishTimer -= diff;
if (AppearEnvenomTimer <= diff) // Appear 2 seconds before becoming attackable (Shifting out of vanish)
{
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveChase(me->GetVictim());
me->SetVisible(true);
AppearEnvenomTimer = 6000;
} else AppearEnvenomTimer -= diff;
}
}
};
};
// SPELL_REFLECTIVE_SHIELD
class spell_boss_lady_malande_shield : public SpellScriptLoader
{
public:
spell_boss_lady_malande_shield() : SpellScriptLoader("spell_boss_lady_malande_shield") { }
class spell_boss_lady_malande_shield_AuraScript : public AuraScript
{
PrepareAuraScript(spell_boss_lady_malande_shield_AuraScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_REFLECTIVE_SHIELD_T });
}
void Trigger(AuraEffect* aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
{
Unit* target = GetTarget();
if (dmgInfo.GetAttacker() == target)
return;
int32 bp = absorbAmount / 2;
target->CastCustomSpell(dmgInfo.GetAttacker(), SPELL_REFLECTIVE_SHIELD_T, &bp, nullptr, nullptr, true, nullptr, aurEff);
}
void Register() override
{
AfterEffectAbsorb += AuraEffectAbsorbFn(spell_boss_lady_malande_shield_AuraScript::Trigger, EFFECT_0);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_boss_lady_malande_shield_AuraScript();
}
};
void AddSC_boss_illidari_council()
{
new npc_illidari_council();
new npc_blood_elf_council_voice_trigger();
new boss_gathios_the_shatterer();
new boss_lady_malande();
new boss_veras_darkshadow();
new boss_high_nethermancer_zerevor();
new spell_boss_lady_malande_shield();
}

View File

@@ -75,7 +75,7 @@ ObjectData const creatureData[] =
{ NPC_VERAS_DARKSHADOW, DATA_VERAS_DARKSHADOW },
{ NPC_BLOOD_ELF_COUNCIL_VOICE, DATA_BLOOD_ELF_COUNCIL_VOICE },
{ NPC_BLACK_TEMPLE_TRIGGER, DATA_BLACK_TEMPLE_TRIGGER },
{ 0, 0 } // end
{ 0, 0 } // END
};
ObjectData const gameObjectData[] =