Scripts/VioletHold: cherry-pick multiple commits from 3.3.5
--- Scripts/VioletHold: picked some things from pull request #11399 (thx MitchedD for initial work) (cherry picked from commit 34a721ba84643cf468f63e5c375949aaa3e15cac) by joschiwald --- Core/Scripts: Rework Violet Hold bosses adding missing spells/mechanics: - Cyanigosa, Arcane Vacuum - Ichoron, globules mechanic - Moragg, optic link visuals - Lavanthor, minor changes - Zuramat, correctly implement void sentries - Erekem, implement Windfury and correct management of Erekem Guards - Script for the pre-event Thx @ManuFe (cherry picked from commit 0bb7f89e82c65f6b750e5d96766c2092031803b5) Conflicts: src/server/scripts/Northrend/VioletHold/boss_erekem.cpp by mik1893 --- Rename 2015_06_08_01_world.sql to 2015_06_25_00_world.sql (cherry picked from commit 8176902b17ce7050029f70a87bec3284c1090785) by MitchesD --- Scripts/VioletHold: fixed non-pch build and codestyle (cherry picked from commit e34f74dacea82f85b3b945e23f3432deda4595b7) by MitchesD --- Scripts/VioletHold: Fix codestyle and unwanted crash in Violet/Hold closes #14952 and #14953 (cherry picked from commit 49809bd404ae7b58ac81086d52297532ec85972a) by mik1893 --- Scripts/VioletHold: fix a crash during Ichoron encounter Closes #14962 (cherry picked from commit 7c01638d45b3eaed7af124a43f21cc6d15407667) by mik1893 --- Core/Misc: Fix build warnings (cherry picked from commit 55681666b3cc0e33eeb5cdb77e638e68c19f452c) Conflicts: src/server/authserver/Main.cpp by jackpoz
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
-- ethereal sphere heroic version
|
||||
UPDATE `creature_template` SET `scriptname` = 'npc_ethereal_sphere' WHERE `entry` = 32582;
|
||||
-- spell script names
|
||||
DELETE FROM `spell_script_names` WHERE `spell_id` IN (58694,54102,54164,54396,54438,54442,57804,59523,59524,61337);
|
||||
INSERT INTO `spell_script_names`(`spell_id`,`ScriptName`) VALUES
|
||||
(54102,'spell_xevozz_summon_ethereal_sphere'),
|
||||
(54164,'spell_xevozz_summon_players'),
|
||||
(54396,'spell_moragg_optic_link'),
|
||||
(54438,'spell_moragg_ray_of_pain'),
|
||||
(54442,'spell_moragg_ray_of_suffering'),
|
||||
(57804,'spell_crystal_activation'),
|
||||
(59523,'spell_moragg_ray_of_pain'),
|
||||
(59524,'spell_moragg_ray_of_suffering'),
|
||||
(61337,'spell_xevozz_summon_ethereal_sphere');
|
||||
-- arcane vacuum summon effect
|
||||
DELETE FROM `spell_linked_spell` WHERE `spell_trigger` = 58694;
|
||||
INSERT INTO `spell_linked_spell` (`spell_trigger`,`spell_effect`,`type`,`comment`) VALUES
|
||||
(58694,21150,1,'Cyanigosa: Arcane Vacuum teleport effect');
|
||||
@@ -23,12 +23,9 @@ enum Spells
|
||||
{
|
||||
SPELL_ARCANE_VACUUM = 58694,
|
||||
SPELL_BLIZZARD = 58693,
|
||||
H_SPELL_BLIZZARD = 59369,
|
||||
SPELL_MANA_DESTRUCTION = 59374,
|
||||
SPELL_TAIL_SWEEP = 58690,
|
||||
H_SPELL_TAIL_SWEEP = 59283,
|
||||
SPELL_UNCONTROLLABLE_ENERGY = 58688,
|
||||
H_SPELL_UNCONTROLLABLE_ENERGY = 59281,
|
||||
SPELL_TRANSFORM = 58668
|
||||
};
|
||||
|
||||
@@ -48,17 +45,11 @@ class boss_cyanigosa : public CreatureScript
|
||||
public:
|
||||
boss_cyanigosa() : CreatureScript("boss_cyanigosa") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
struct boss_cyanigosaAI : public BossAI
|
||||
{
|
||||
return GetInstanceAI<boss_cyanigosaAI>(creature);
|
||||
}
|
||||
|
||||
struct boss_cyanigosaAI : public ScriptedAI
|
||||
{
|
||||
boss_cyanigosaAI(Creature* creature) : ScriptedAI(creature)
|
||||
boss_cyanigosaAI(Creature* creature) : BossAI(creature, DATA_CYANIGOSA)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
@@ -76,24 +67,20 @@ public:
|
||||
uint32 uiTailSweepTimer;
|
||||
uint32 uiUncontrollableEnergyTimer;
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
instance->SetData(DATA_CYANIGOSA_EVENT, NOT_STARTED);
|
||||
BossAI::Reset();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
instance->SetData(DATA_CYANIGOSA_EVENT, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (instance->GetData(DATA_REMOVE_NPC) == 1)
|
||||
@@ -102,13 +89,12 @@ public:
|
||||
instance->SetData(DATA_REMOVE_NPC, 0);
|
||||
}
|
||||
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (uiArcaneVacuumTimer <= diff)
|
||||
{
|
||||
DoCast(SPELL_ARCANE_VACUUM);
|
||||
DoCastAOE(SPELL_ARCANE_VACUUM);
|
||||
uiArcaneVacuumTimer = 10000;
|
||||
} else uiArcaneVacuumTimer -= diff;
|
||||
|
||||
@@ -121,7 +107,7 @@ public:
|
||||
|
||||
if (uiTailSweepTimer <= diff)
|
||||
{
|
||||
DoCast(SPELL_TAIL_SWEEP);
|
||||
DoCastVictim(SPELL_TAIL_SWEEP);
|
||||
uiTailSweepTimer = 20000;
|
||||
} else uiTailSweepTimer -= diff;
|
||||
|
||||
@@ -144,22 +130,23 @@ public:
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
instance->SetData(DATA_CYANIGOSA_EVENT, DONE);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
Talk(SAY_SLAY);
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<boss_cyanigosaAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class achievement_defenseless : public AchievementCriteriaScript
|
||||
|
||||
@@ -24,12 +24,11 @@ enum Spells
|
||||
SPELL_BLOODLUST = 54516,
|
||||
SPELL_BREAK_BONDS = 59463,
|
||||
SPELL_CHAIN_HEAL = 54481,
|
||||
H_SPELL_CHAIN_HEAL = 59473,
|
||||
SPELL_EARTH_SHIELD = 54479,
|
||||
H_SPELL_EARTH_SHIELD = 59471,
|
||||
SPELL_EARTH_SHOCK = 54511,
|
||||
SPELL_LIGHTNING_BOLT = 53044,
|
||||
SPELL_STORMSTRIKE = 51876
|
||||
SPELL_STORMSTRIKE = 51876,
|
||||
SPELL_WINDFURY = 54493
|
||||
};
|
||||
|
||||
enum Yells
|
||||
@@ -42,6 +41,17 @@ enum Yells
|
||||
SAY_BOTH_ADDS_KILLED = 5
|
||||
};
|
||||
|
||||
enum ErekemEvents
|
||||
{
|
||||
EVENT_EARTH_SHIELD = 1,
|
||||
EVENT_CHAIN_HEAL,
|
||||
EVENT_BLOODLUST,
|
||||
EVENT_LIGHTNING_BOLT,
|
||||
EVENT_EARTH_SHOCK,
|
||||
EVENT_WINDFURY,
|
||||
EVENT_STORMSTRIKE
|
||||
};
|
||||
|
||||
class boss_erekem : public CreatureScript
|
||||
{
|
||||
public:
|
||||
@@ -62,39 +72,50 @@ public:
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
uiBloodlustTimer = 15000;
|
||||
uiChainHealTimer = 0;
|
||||
uiEarthShockTimer = urand(2000, 8000);
|
||||
uiLightningBoltTimer = urand(5000, 10000);
|
||||
uiEarthShieldTimer = 20000;
|
||||
phase = 0;
|
||||
breakBondsCd = 0;
|
||||
}
|
||||
|
||||
uint32 uiBloodlustTimer;
|
||||
uint32 uiChainHealTimer;
|
||||
uint32 uiEarthShockTimer;
|
||||
uint32 uiLightningBoltTimer;
|
||||
uint32 uiEarthShieldTimer;
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
|
||||
if (instance->GetData(DATA_MAIN_EVENT_PHASE) == IN_PROGRESS)
|
||||
{
|
||||
if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)))
|
||||
pGuard1->DespawnOrUnsummon();
|
||||
if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2)))
|
||||
pGuard2->DespawnOrUnsummon();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)))
|
||||
{
|
||||
if (!pGuard1->IsAlive())
|
||||
pGuard1->Respawn();
|
||||
}
|
||||
if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2)))
|
||||
{
|
||||
if (!pGuard2->IsAlive())
|
||||
pGuard2->Respawn();
|
||||
}
|
||||
}
|
||||
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)))
|
||||
{
|
||||
if (!pGuard1->IsAlive())
|
||||
pGuard1->Respawn();
|
||||
}
|
||||
pGuard1->Respawn();
|
||||
|
||||
if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2)))
|
||||
{
|
||||
if (!pGuard2->IsAlive())
|
||||
pGuard2->Respawn();
|
||||
}
|
||||
pGuard2->Respawn();
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
@@ -111,13 +132,13 @@ public:
|
||||
|
||||
if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)))
|
||||
{
|
||||
pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE);
|
||||
pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
if (!pGuard1->GetVictim() && pGuard1->AI())
|
||||
pGuard1->AI()->AttackStart(who);
|
||||
}
|
||||
if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2)))
|
||||
{
|
||||
pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE);
|
||||
pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
if (!pGuard2->GetVictim() && pGuard2->AI())
|
||||
pGuard2->AI()->AttackStart(who);
|
||||
}
|
||||
@@ -129,82 +150,24 @@ public:
|
||||
Talk(SAY_AGGRO);
|
||||
DoCast(me, SPELL_EARTH_SHIELD);
|
||||
|
||||
if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_EREKEM_CELL)))
|
||||
if (pDoor->GetGoState() == GO_STATE_READY)
|
||||
if (GameObject* door = instance->GetGameObject(DATA_EREKEM_CELL))
|
||||
if (door->GetGoState() == GO_STATE_READY)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
}
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
//spam stormstrike in hc mode if spawns are dead
|
||||
if (IsHeroic())
|
||||
{
|
||||
if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)))
|
||||
{
|
||||
if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2)))
|
||||
{
|
||||
if (!pGuard1->IsAlive() && !pGuard2->IsAlive())
|
||||
DoCastVictim(SPELL_STORMSTRIKE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uiEarthShieldTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_EARTH_SHIELD);
|
||||
uiEarthShieldTimer = 20000;
|
||||
} else uiEarthShieldTimer -= diff;
|
||||
|
||||
if (uiChainHealTimer <= diff)
|
||||
{
|
||||
ObjectGuid TargetGUID = GetChainHealTargetGUID();
|
||||
if (!TargetGUID.IsEmpty())
|
||||
{
|
||||
if (Creature* target = ObjectAccessor::GetCreature(*me, TargetGUID))
|
||||
DoCast(target, SPELL_CHAIN_HEAL);
|
||||
|
||||
//If one of the adds is dead spawn heals faster
|
||||
Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1));
|
||||
Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2));
|
||||
uiChainHealTimer = ((pGuard1 && !pGuard1->IsAlive()) || (pGuard2 && !pGuard2->IsAlive()) ? 3000 : 8000) + rand32() % 3000;
|
||||
}
|
||||
} else uiChainHealTimer -= diff;
|
||||
|
||||
if (uiBloodlustTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_BLOODLUST);
|
||||
uiBloodlustTimer = urand(35000, 45000);
|
||||
} else uiBloodlustTimer -= diff;
|
||||
|
||||
if (uiEarthShockTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_EARTH_SHOCK);
|
||||
uiEarthShockTimer = urand(8000, 13000);
|
||||
} else uiEarthShockTimer -= diff;
|
||||
|
||||
if (uiLightningBoltTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_LIGHTNING_BOLT);
|
||||
uiLightningBoltTimer = urand(18000, 24000);
|
||||
} else uiLightningBoltTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
events.ScheduleEvent(EVENT_EARTH_SHIELD, 20000);
|
||||
events.ScheduleEvent(EVENT_BLOODLUST, 15000);
|
||||
events.ScheduleEvent(EVENT_CHAIN_HEAL, 10000);
|
||||
events.ScheduleEvent(EVENT_LIGHTNING_BOLT, 2000);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -213,41 +176,134 @@ public:
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
{
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 7);
|
||||
}
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
{
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, DONE);
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 13);
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() != TYPEID_PLAYER)
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
Talk(SAY_SLAY);
|
||||
if (phase == 0)
|
||||
if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)))
|
||||
{
|
||||
if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2)))
|
||||
{
|
||||
if (!pGuard1->IsAlive() && !pGuard2->IsAlive())
|
||||
{
|
||||
phase = 1;
|
||||
DoCastVictim(SPELL_STORMSTRIKE);
|
||||
DoCast(SPELL_WINDFURY);
|
||||
events.Reset();
|
||||
events.ScheduleEvent(EVENT_EARTH_SHOCK, urand(2000, 8000));
|
||||
events.ScheduleEvent(EVENT_WINDFURY, urand(1500, 2000));
|
||||
events.ScheduleEvent(EVENT_STORMSTRIKE, urand(1500, 2000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
if (breakBondsCd <= 0)
|
||||
{
|
||||
if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)))
|
||||
{
|
||||
if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2)))
|
||||
{
|
||||
if (pGuard1->IsAlive())
|
||||
{
|
||||
if (pGuard1->HasAuraType(SPELL_AURA_MOD_STUN) || pGuard1->HasAuraType(SPELL_AURA_MOD_ROOT)
|
||||
|| pGuard1->HasAuraType(SPELL_AURA_MOD_CONFUSE) || pGuard1->HasAuraType(SPELL_AURA_MOD_PACIFY)
|
||||
|| pGuard1->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED))
|
||||
{
|
||||
DoCast(SPELL_BREAK_BONDS);
|
||||
breakBondsCd = 10000;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (pGuard2->IsAlive())
|
||||
{
|
||||
if (pGuard2->HasAuraType(SPELL_AURA_MOD_STUN) || pGuard2->HasAuraType(SPELL_AURA_MOD_ROOT)
|
||||
|| pGuard2->HasAuraType(SPELL_AURA_MOD_CONFUSE) || pGuard2->HasAuraType(SPELL_AURA_MOD_PACIFY)
|
||||
|| pGuard2->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED))
|
||||
{
|
||||
DoCast(SPELL_BREAK_BONDS);
|
||||
breakBondsCd = 10000;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
breakBondsCd -= diff;
|
||||
|
||||
switch (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_EARTH_SHIELD:
|
||||
if (Unit* ally = DoSelectLowestHpFriendly(30.0f))
|
||||
DoCast(ally, SPELL_EARTH_SHIELD);
|
||||
events.ScheduleEvent(EVENT_EARTH_SHIELD, 20000);
|
||||
break;
|
||||
case EVENT_BLOODLUST:
|
||||
DoCast(SPELL_BLOODLUST);
|
||||
events.ScheduleEvent(EVENT_BLOODLUST, urand(35000, 45000));
|
||||
break;
|
||||
case EVENT_LIGHTNING_BOLT:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(target, SPELL_LIGHTNING_BOLT);
|
||||
events.ScheduleEvent(EVENT_LIGHTNING_BOLT, 2500);
|
||||
break;
|
||||
case EVENT_CHAIN_HEAL:
|
||||
if (Unit* ally = DoSelectLowestHpFriendly(40.0f))
|
||||
DoCast(ally, SPELL_CHAIN_HEAL);
|
||||
{
|
||||
Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1));
|
||||
Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2));
|
||||
events.ScheduleEvent(EVENT_CHAIN_HEAL, ((pGuard1 && !pGuard1->IsAlive()) || (pGuard2 && !pGuard2->IsAlive()) ? 3000 : 8000 + rand() % 3000));
|
||||
}
|
||||
break;
|
||||
case EVENT_EARTH_SHOCK:
|
||||
DoCastVictim(SPELL_EARTH_SHOCK);
|
||||
events.ScheduleEvent(EVENT_EARTH_SHOCK, urand(8000, 13000));
|
||||
break;
|
||||
case EVENT_WINDFURY:
|
||||
DoCast(SPELL_WINDFURY);
|
||||
events.ScheduleEvent(EVENT_WINDFURY, urand(1500, 2000));
|
||||
break;
|
||||
case EVENT_STORMSTRIKE:
|
||||
DoCastVictim(SPELL_STORMSTRIKE);
|
||||
events.ScheduleEvent(EVENT_STORMSTRIKE, urand(1500, 2000));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
ObjectGuid GetChainHealTargetGUID()
|
||||
{
|
||||
if (HealthBelowPct(85))
|
||||
return me->GetGUID();
|
||||
|
||||
Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1));
|
||||
if (pGuard1 && pGuard1->IsAlive() && !pGuard1->HealthAbovePct(75))
|
||||
return pGuard1->GetGUID();
|
||||
|
||||
Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2));
|
||||
if (pGuard2 && pGuard2->IsAlive() && !pGuard2->HealthAbovePct(75))
|
||||
return pGuard2->GetGUID();
|
||||
|
||||
return ObjectGuid::Empty;
|
||||
}
|
||||
private:
|
||||
EventMap events;
|
||||
InstanceScript* instance;
|
||||
uint8 phase;
|
||||
int32 breakBondsCd;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
enum GuardSpells
|
||||
@@ -291,6 +347,9 @@ public:
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
@@ -309,7 +368,6 @@ public:
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
@@ -336,7 +394,6 @@ public:
|
||||
} else uiGushingWoundTimer -= diff;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
void AddSC_boss_erekem()
|
||||
|
||||
@@ -23,19 +23,20 @@ enum Spells
|
||||
{
|
||||
SPELL_DRAINED = 59820,
|
||||
SPELL_FRENZY = 54312,
|
||||
SPELL_FRENZY_H = 59522,
|
||||
SPELL_PROTECTIVE_BUBBLE = 54306,
|
||||
SPELL_WATER_BLAST = 54237,
|
||||
SPELL_WATER_BLAST_H = 59520,
|
||||
SPELL_WATER_BOLT_VOLLEY = 54241,
|
||||
SPELL_WATER_BOLT_VOLLEY_H = 59521,
|
||||
SPELL_SPLASH = 59516,
|
||||
SPELL_WATER_GLOBULE = 54268
|
||||
SPELL_BURST = 54379,
|
||||
SPELL_WATER_GLOBULE = 54268,
|
||||
SPELL_MERGE = 54269,
|
||||
SPELL_WATER_GLOBULE_VISUAL = 54260
|
||||
};
|
||||
|
||||
enum IchoronCreatures
|
||||
{
|
||||
NPC_ICHOR_GLOBULE = 29321,
|
||||
NPC_ICHORON_SUMMON_TARGET = 29326
|
||||
};
|
||||
|
||||
enum Yells
|
||||
@@ -51,75 +52,83 @@ enum Yells
|
||||
|
||||
enum Actions
|
||||
{
|
||||
ACTION_WATER_ELEMENT_HIT = 1,
|
||||
ACTION_WATER_ELEMENT_KILLED = 2,
|
||||
ACTION_WATER_ELEMENT_HIT = 1
|
||||
};
|
||||
|
||||
/// @todo get those positions from spawn of creature 29326
|
||||
#define MAX_SPAWN_LOC 5
|
||||
static Position SpawnLoc[MAX_SPAWN_LOC]=
|
||||
enum IchoronEvents
|
||||
{
|
||||
{1840.64f, 795.407f, 44.079f, 1.676f},
|
||||
{1886.24f, 757.733f, 47.750f, 5.201f},
|
||||
{1877.91f, 845.915f, 43.417f, 3.560f},
|
||||
{1918.97f, 850.645f, 47.225f, 4.136f},
|
||||
{1935.50f, 796.224f, 52.492f, 4.224f},
|
||||
EVENT_WATER_BLAST = 1,
|
||||
EVENT_WATER_BOLT_VOLLEY
|
||||
};
|
||||
|
||||
enum GlobuleEvents
|
||||
{
|
||||
EVENT_GLOBULE_MOVE = 1
|
||||
};
|
||||
|
||||
enum Misc
|
||||
{
|
||||
DATA_GLOBULE_PATH = 0,
|
||||
DATA_DEHYDRATION = 1
|
||||
};
|
||||
|
||||
|
||||
#define MAX_GLOBULE_PATHS 10
|
||||
|
||||
Position const globulePaths[MAX_GLOBULE_PATHS] =
|
||||
{
|
||||
// first target
|
||||
{ 1861.357f, 804.039f, 44.008f, 6.268f },
|
||||
{ 1869.375f, 803.976f, 38.781f, 0.009f },
|
||||
// second target
|
||||
{ 1888.063f, 763.488f, 47.667f, 1.744f },
|
||||
{ 1882.865f, 776.385f, 38.824f, 1.882f },
|
||||
// third target
|
||||
{ 1935.140f, 817.752f, 52.181f, 1.885f },
|
||||
{ 1916.642f, 826.337f, 39.139f, 2.851f },
|
||||
// fourth target
|
||||
{ 1930.257f, 833.053f, 46.906f, 4.579f },
|
||||
{ 1916.642f, 826.337f, 39.139f, 2.851f },
|
||||
// fifth target
|
||||
{ 1878.248f, 841.883f, 43.334f, 4.717f },
|
||||
{ 1879.438f, 834.443f, 38.699f, 4.831f }
|
||||
};
|
||||
|
||||
class boss_ichoron : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_ichoron() : CreatureScript("boss_ichoron") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<boss_ichoronAI>(creature);
|
||||
}
|
||||
|
||||
struct boss_ichoronAI : public ScriptedAI
|
||||
{
|
||||
boss_ichoronAI(Creature* creature) : ScriptedAI(creature), m_waterElements(creature)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
bIsExploded = false;
|
||||
bIsFrenzy = false;
|
||||
bIsDrained = false;
|
||||
dehydration = true;
|
||||
uiBubbleCheckerTimer = 1000;
|
||||
uiWaterBoltVolleyTimer = urand(10000, 15000);
|
||||
drainedTimer = 50;
|
||||
burstTimer = 15000;
|
||||
}
|
||||
|
||||
bool bIsExploded;
|
||||
bool bIsFrenzy;
|
||||
bool dehydration;
|
||||
|
||||
uint32 uiBubbleCheckerTimer;
|
||||
uint32 uiWaterBoltVolleyTimer;
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
SummonList m_waterElements;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
|
||||
events.Reset();
|
||||
me->SetVisible(true);
|
||||
DespawnWaterElements();
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED);
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
@@ -128,16 +137,20 @@ public:
|
||||
|
||||
DoCast(me, SPELL_PROTECTIVE_BUBBLE);
|
||||
|
||||
if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_ICHORON_CELL)))
|
||||
if (pDoor->GetGoState() == GO_STATE_READY)
|
||||
if (GameObject* door = instance->GetGameObject(DATA_ICHORON_CELL))
|
||||
if (door->GetGoState() == GO_STATE_READY)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
|
||||
events.ScheduleEvent(EVENT_WATER_BOLT_VOLLEY, urand(10000, 15000));
|
||||
events.ScheduleEvent(EVENT_WATER_BLAST, urand(6000, 9000));
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
@@ -162,18 +175,14 @@ public:
|
||||
switch (param)
|
||||
{
|
||||
case ACTION_WATER_ELEMENT_HIT:
|
||||
me->ModifyHealth(int32(me->CountPctFromMaxHealth(1)));
|
||||
|
||||
{
|
||||
if (bIsExploded)
|
||||
DoExplodeCompleted();
|
||||
|
||||
me->SetHealth(me->GetHealth() + me->CountPctFromMaxHealth(3));
|
||||
dehydration = false;
|
||||
break;
|
||||
case ACTION_WATER_ELEMENT_KILLED:
|
||||
uint32 damage = me->CountPctFromMaxHealth(3);
|
||||
me->ModifyHealth(-int32(damage));
|
||||
me->LowerPlayerDamageReq(damage);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +196,7 @@ public:
|
||||
void DoExplodeCompleted()
|
||||
{
|
||||
bIsExploded = false;
|
||||
bIsDrained = false;
|
||||
|
||||
if (!HealthBelowPct(25))
|
||||
{
|
||||
@@ -206,75 +216,24 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
|
||||
void UpdateAI(uint32 uiDiff) override
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
if (!who->ToCreature())
|
||||
return;
|
||||
|
||||
if (!bIsFrenzy && HealthBelowPct(25) && !bIsExploded)
|
||||
{
|
||||
Talk(SAY_ENRAGE);
|
||||
DoCast(me, SPELL_FRENZY, true);
|
||||
bIsFrenzy = true;
|
||||
}
|
||||
if (who->GetEntry() != NPC_ICHOR_GLOBULE)
|
||||
return;
|
||||
|
||||
if (!bIsFrenzy)
|
||||
{
|
||||
if (uiBubbleCheckerTimer <= uiDiff)
|
||||
{
|
||||
if (!bIsExploded)
|
||||
{
|
||||
if (!me->HasAura(SPELL_PROTECTIVE_BUBBLE))
|
||||
{
|
||||
Talk(SAY_SHATTER);
|
||||
DoCast(me, SPELL_WATER_BLAST);
|
||||
DoCast(me, SPELL_DRAINED);
|
||||
bIsExploded = true;
|
||||
me->AttackStop();
|
||||
me->SetVisible(false);
|
||||
for (uint8 i = 0; i < 10; i++)
|
||||
{
|
||||
int tmp = urand(0, MAX_SPAWN_LOC-1);
|
||||
me->SummonCreature(NPC_ICHOR_GLOBULE, SpawnLoc[tmp], TEMPSUMMON_CORPSE_DESPAWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool bIsWaterElementsAlive = false;
|
||||
if (!m_waterElements.empty())
|
||||
{
|
||||
for (SummonList::const_iterator itr = m_waterElements.begin(); itr != m_waterElements.end(); ++itr)
|
||||
if (Creature* temp = ObjectAccessor::GetCreature(*me, *itr))
|
||||
if (temp->IsAlive())
|
||||
{
|
||||
bIsWaterElementsAlive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!me->IsWithinDist(who, 4.0f, false))
|
||||
return;
|
||||
|
||||
if (!bIsWaterElementsAlive)
|
||||
DoExplodeCompleted();
|
||||
}
|
||||
uiBubbleCheckerTimer = 1000;
|
||||
}
|
||||
else uiBubbleCheckerTimer -= uiDiff;
|
||||
}
|
||||
if (who->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
|
||||
return;
|
||||
|
||||
if (!bIsExploded)
|
||||
{
|
||||
if (uiWaterBoltVolleyTimer <= uiDiff)
|
||||
{
|
||||
DoCast(me, SPELL_WATER_BOLT_VOLLEY);
|
||||
uiWaterBoltVolleyTimer = urand(10000, 15000);
|
||||
}
|
||||
else uiWaterBoltVolleyTimer -= uiDiff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
who->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
who->CastSpell(who, SPELL_MERGE);
|
||||
DoAction(ACTION_WATER_ELEMENT_HIT);
|
||||
who->ToCreature()->DespawnOrUnsummon(1000);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -291,45 +250,187 @@ public:
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
{
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 7);
|
||||
}
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
{
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, DONE);
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 13);
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summoned) override
|
||||
{
|
||||
if (summoned)
|
||||
{
|
||||
summoned->SetSpeed(MOVE_RUN, 0.3f);
|
||||
summoned->GetMotionMaster()->MoveFollow(me, 0, 0);
|
||||
m_waterElements.Summon(summoned);
|
||||
instance->SetGuidData(DATA_ADD_TRASH_MOB, summoned->GetGUID());
|
||||
}
|
||||
summoned->SetSpeed(MOVE_RUN, 0.3f);
|
||||
m_waterElements.Summon(summoned);
|
||||
|
||||
instance->SetGuidData(DATA_ADD_TRASH_MOB, summoned->GetGUID());
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* summoned) override
|
||||
{
|
||||
if (summoned)
|
||||
m_waterElements.Despawn(summoned);
|
||||
|
||||
if (m_waterElements.empty() && bIsExploded)
|
||||
{
|
||||
m_waterElements.Despawn(summoned);
|
||||
instance->SetGuidData(DATA_DEL_TRASH_MOB, summoned->GetGUID());
|
||||
me->RemoveAllAuras();
|
||||
DoExplodeCompleted();
|
||||
}
|
||||
|
||||
instance->SetGuidData(DATA_DEL_TRASH_MOB, summoned->GetGUID());
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() != TYPEID_PLAYER)
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
Talk(SAY_SLAY);
|
||||
if (!bIsFrenzy && HealthBelowPct(25) && !bIsExploded)
|
||||
{
|
||||
Talk(SAY_ENRAGE);
|
||||
DoCast(me, SPELL_FRENZY, true);
|
||||
bIsFrenzy = true;
|
||||
}
|
||||
|
||||
if (!bIsFrenzy)
|
||||
{
|
||||
if (!bIsExploded)
|
||||
{
|
||||
if (!me->HasAura(SPELL_PROTECTIVE_BUBBLE))
|
||||
{
|
||||
bIsExploded = true;
|
||||
Talk(SAY_SHATTER);
|
||||
DoCast(SPELL_BURST);
|
||||
me->RemoveAllAuras();
|
||||
burstTimer = 15000;
|
||||
|
||||
std::list<Creature*> summonTargets;
|
||||
GetCreatureListWithEntryInGrid(summonTargets, me, NPC_ICHORON_SUMMON_TARGET, 200.0f);
|
||||
std::list<Creature*>::iterator itr = summonTargets.begin();
|
||||
|
||||
for (uint8 i = 0; i < MAX_GLOBULE_PATHS; i++)
|
||||
{
|
||||
std::advance(itr, urand(0, summonTargets.size() - 1)); // I take a random minion in the list
|
||||
Position targetPos = (*itr)->GetRandomNearPosition(10.0f);
|
||||
itr = summonTargets.begin();
|
||||
TempSummon* globule = me->SummonCreature(NPC_ICHOR_GLOBULE, targetPos, TEMPSUMMON_CORPSE_DESPAWN);
|
||||
DoCast(globule, SPELL_WATER_GLOBULE_VISUAL);
|
||||
|
||||
float minDistance = 1000.0f;
|
||||
uint8 nextPath = 0;
|
||||
// I move the globules to next position. the 10 positions are in couples, defined in globulePaths, so i have to increase by 2.
|
||||
for (uint8 gpath = 0; gpath < MAX_GLOBULE_PATHS; gpath += 2)
|
||||
{
|
||||
if (globule->GetDistance(globulePaths[gpath]) < minDistance)
|
||||
{
|
||||
minDistance = globule->GetDistance(globulePaths[gpath]);
|
||||
nextPath = gpath;
|
||||
}
|
||||
}
|
||||
|
||||
globule->GetAI()->SetData(DATA_GLOBULE_PATH, nextPath);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
switch (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_WATER_BLAST:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(target, SPELL_WATER_BLAST);
|
||||
events.ScheduleEvent(EVENT_WATER_BLAST, urand(6000, 9000));
|
||||
break;
|
||||
case EVENT_WATER_BOLT_VOLLEY:
|
||||
DoCast(SPELL_WATER_BOLT_VOLLEY);
|
||||
events.ScheduleEvent(EVENT_WATER_BOLT_VOLLEY, urand(10000, 15000));
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
else if (!bIsDrained)
|
||||
{
|
||||
if (drainedTimer <= 0)
|
||||
{
|
||||
bIsDrained = true;
|
||||
drainedTimer = 50;
|
||||
uint32 damage = me->CountPctFromMaxHealth(30);
|
||||
if (me->GetHealth() < damage)
|
||||
me->SetHealth(me->CountPctFromMaxHealth(1));
|
||||
else
|
||||
{
|
||||
me->SetHealth(me->GetHealth() - damage);
|
||||
me->LowerPlayerDamageReq(damage);
|
||||
}
|
||||
DoCast(SPELL_DRAINED);
|
||||
me->SetVisible(false);
|
||||
me->AttackStop();
|
||||
}
|
||||
else
|
||||
drainedTimer -= diff;
|
||||
}
|
||||
else if (bIsDrained)
|
||||
{
|
||||
if (burstTimer <= 0)
|
||||
{
|
||||
DoExplodeCompleted();
|
||||
}
|
||||
else
|
||||
burstTimer -= diff;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
switch (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_WATER_BLAST:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(target, SPELL_WATER_BLAST);
|
||||
events.ScheduleEvent(EVENT_WATER_BLAST, urand(6000, 9000));
|
||||
break;
|
||||
case EVENT_WATER_BOLT_VOLLEY:
|
||||
DoCast(SPELL_WATER_BOLT_VOLLEY);
|
||||
events.ScheduleEvent(EVENT_WATER_BOLT_VOLLEY, urand(10000, 15000));
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
SummonList m_waterElements;
|
||||
EventMap events;
|
||||
bool bIsExploded;
|
||||
bool bIsFrenzy;
|
||||
bool bIsDrained;
|
||||
bool dehydration;
|
||||
int32 drainedTimer;
|
||||
int32 burstTimer;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<boss_ichoronAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_ichor_globule : public CreatureScript
|
||||
@@ -337,11 +438,6 @@ class npc_ichor_globule : public CreatureScript
|
||||
public:
|
||||
npc_ichor_globule() : CreatureScript("npc_ichor_globule") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_ichor_globuleAI>(creature);
|
||||
}
|
||||
|
||||
struct npc_ichor_globuleAI : public ScriptedAI
|
||||
{
|
||||
npc_ichor_globuleAI(Creature* creature) : ScriptedAI(creature)
|
||||
@@ -352,51 +448,74 @@ public:
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
uiRangeCheck_Timer = 1000;
|
||||
pathId = 0;
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint32 uiRangeCheck_Timer;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
DoCast(me, SPELL_WATER_GLOBULE);
|
||||
events.Reset();
|
||||
DoCast(SPELL_WATER_GLOBULE);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* /*who*/) override
|
||||
void SetData(uint32 id, uint32 data) override
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 uiDiff) override
|
||||
{
|
||||
if (uiRangeCheck_Timer < uiDiff)
|
||||
if (id == DATA_GLOBULE_PATH)
|
||||
{
|
||||
if (Creature* pIchoron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ICHORON)))
|
||||
{
|
||||
if (me->IsWithinDist(pIchoron, 2.0f, false))
|
||||
{
|
||||
if (pIchoron->AI())
|
||||
pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_HIT);
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
uiRangeCheck_Timer = 1000;
|
||||
pathId = data;
|
||||
me->GetMotionMaster()->MovePoint(0, globulePaths[pathId]);
|
||||
}
|
||||
else uiRangeCheck_Timer -= uiDiff;
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
DoCast(me, SPELL_SPLASH);
|
||||
if (Creature* pIchoron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ICHORON)))
|
||||
if (pIchoron->AI())
|
||||
pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_KILLED);
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case 0:
|
||||
me->GetMotionMaster()->Clear();
|
||||
events.ScheduleEvent(EVENT_GLOBULE_MOVE, 500);
|
||||
break;
|
||||
case 1:
|
||||
me->GetMotionMaster()->Clear();
|
||||
if (Creature* ichoron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ICHORON)))
|
||||
me->GetMotionMaster()->MoveFollow(ichoron, 0.0f, 0.0f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// on retail spell casted on a creature's death are not casted after death but keeping mob at 1 health, casting it and then letting the mob die.
|
||||
// this feature should be still implemented
|
||||
void DamageTaken(Unit* /*attacker*/, uint32 &damage) override
|
||||
{
|
||||
int32 actualHp = me->GetHealth();
|
||||
actualHp -= damage;
|
||||
|
||||
if (actualHp <= 0)
|
||||
DoCast(SPELL_SPLASH);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events.Update(diff);
|
||||
|
||||
if (events.ExecuteEvent() == EVENT_GLOBULE_MOVE)
|
||||
me->GetMotionMaster()->MovePoint(1, globulePaths[pathId + 1]);
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
uint8 pathId;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_ichor_globuleAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class achievement_dehydration : public AchievementCriteriaScript
|
||||
|
||||
@@ -21,13 +21,18 @@
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_CAUTERIZING_FLAMES = 59466, //Only in heroic
|
||||
SPELL_FIREBOLT = 54235,
|
||||
H_SPELL_FIREBOLT = 59468,
|
||||
SPELL_FLAME_BREATH = 54282,
|
||||
H_SPELL_FLAME_BREATH = 59469,
|
||||
SPELL_LAVA_BURN = 54249,
|
||||
H_SPELL_LAVA_BURN = 59594
|
||||
SPELL_CAUTERIZING_FLAMES = 59466, // Only in heroic
|
||||
SPELL_FIREBOLT = 54235,
|
||||
SPELL_FLAME_BREATH = 54282,
|
||||
SPELL_LAVA_BURN = 54249
|
||||
};
|
||||
|
||||
enum LavanthorEvents
|
||||
{
|
||||
EVENT_CAUTERIZING_FLAMES = 1,
|
||||
EVENT_FIREBOLT,
|
||||
EVENT_FLAME_BREATH,
|
||||
EVENT_LAVA_BURN
|
||||
};
|
||||
|
||||
class boss_lavanthor : public CreatureScript
|
||||
@@ -44,46 +49,37 @@ public:
|
||||
{
|
||||
boss_lavanthorAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
uiFireboltTimer = 1000;
|
||||
uiFlameBreathTimer = 5000;
|
||||
uiLavaBurnTimer = 10000;
|
||||
uiCauterizingFlamesTimer = 3000;
|
||||
}
|
||||
|
||||
uint32 uiFireboltTimer;
|
||||
uint32 uiFlameBreathTimer;
|
||||
uint32 uiLavaBurnTimer;
|
||||
uint32 uiCauterizingFlamesTimer;
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED);
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_LAVANTHOR_CELL)))
|
||||
if (pDoor->GetGoState() == GO_STATE_READY)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
if (GameObject* door = instance->GetGameObject(DATA_LAVANTHOR_CELL))
|
||||
if (door->GetGoState() == GO_STATE_READY)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
|
||||
events.ScheduleEvent(EVENT_FIREBOLT, 1000);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREATH, 5000);
|
||||
events.ScheduleEvent(EVENT_LAVA_BURN, 10000);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_CAUTERIZING_FLAMES, 3000);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
@@ -100,40 +96,38 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (uiFireboltTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_FIREBOLT);
|
||||
uiFireboltTimer = urand(5000, 13000);
|
||||
} else uiFireboltTimer -= diff;
|
||||
events.Update(diff);
|
||||
|
||||
if (uiFlameBreathTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_FLAME_BREATH);
|
||||
uiFlameBreathTimer = urand(10000, 15000);
|
||||
} else uiFlameBreathTimer -= diff;
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
if (uiLavaBurnTimer <= diff)
|
||||
switch (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
DoCastVictim(SPELL_LAVA_BURN);
|
||||
uiLavaBurnTimer = urand(15000, 23000);
|
||||
}
|
||||
|
||||
if (IsHeroic())
|
||||
{
|
||||
if (uiCauterizingFlamesTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_CAUTERIZING_FLAMES);
|
||||
uiCauterizingFlamesTimer = urand(10000, 16000);
|
||||
} else uiCauterizingFlamesTimer -= diff;
|
||||
case EVENT_FIREBOLT:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(target, SPELL_FIREBOLT);
|
||||
events.ScheduleEvent(EVENT_FIREBOLT, urand(5000, 13000));
|
||||
break;
|
||||
case EVENT_FLAME_BREATH:
|
||||
DoCast(SPELL_FLAME_BREATH);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREATH, urand(10000, 15000));
|
||||
break;
|
||||
case EVENT_LAVA_BURN:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(target, SPELL_LAVA_BURN);
|
||||
events.ScheduleEvent(EVENT_LAVA_BURN, urand(15000, 23000));
|
||||
break;
|
||||
case EVENT_CAUTERIZING_FLAMES:
|
||||
DoCast(SPELL_CAUTERIZING_FLAMES);
|
||||
events.ScheduleEvent(EVENT_CAUTERIZING_FLAMES, urand(10000, 16000));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
@@ -143,17 +137,20 @@ public:
|
||||
{
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
{
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 7);
|
||||
}
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
{
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, DONE);
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 13);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
EventMap events;
|
||||
InstanceScript* instance;
|
||||
};
|
||||
};
|
||||
|
||||
void AddSC_boss_lavanthor()
|
||||
|
||||
@@ -17,13 +17,27 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "violet_hold.h"
|
||||
|
||||
//Spells
|
||||
enum Spells
|
||||
{
|
||||
SPELL_CORROSIVE_SALIVA = 54527,
|
||||
SPELL_OPTIC_LINK = 54396
|
||||
SPELL_OPTIC_LINK = 54396,
|
||||
SPELL_RAY_OF_PAIN = 54438, // NYI missing spelldifficulty
|
||||
SPELL_RAY_OF_SUFFERING = 54442, // NYI missing spelldifficulty
|
||||
|
||||
// Visual
|
||||
SPELL_OPTIC_LINK_LEVEL_1 = 54393,
|
||||
SPELL_OPTIC_LINK_LEVEL_2 = 54394,
|
||||
SPELL_OPTIC_LINK_LEVEL_3 = 54395
|
||||
};
|
||||
|
||||
enum MoraggEvents
|
||||
{
|
||||
EVENT_CORROSIVE_SALIVA = 1,
|
||||
EVENT_OPTIC_LINK
|
||||
};
|
||||
|
||||
class boss_moragg : public CreatureScript
|
||||
@@ -31,52 +45,43 @@ class boss_moragg : public CreatureScript
|
||||
public:
|
||||
boss_moragg() : CreatureScript("boss_moragg") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<boss_moraggAI>(creature);
|
||||
}
|
||||
|
||||
struct boss_moraggAI : public ScriptedAI
|
||||
{
|
||||
boss_moraggAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
uiOpticLinkTimer = 10000;
|
||||
uiCorrosiveSalivaTimer = 5000;
|
||||
}
|
||||
|
||||
uint32 uiOpticLinkTimer;
|
||||
uint32 uiCorrosiveSalivaTimer;
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
events.Reset();
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED);
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_MORAGG_CELL)))
|
||||
if (pDoor->GetGoState() == GO_STATE_READY)
|
||||
if (GameObject* door = instance->GetGameObject(DATA_MORAGG_CELL))
|
||||
if (door->GetGoState() == GO_STATE_READY)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
|
||||
me->SetInCombatWithZone();
|
||||
|
||||
DoCast(SPELL_RAY_OF_PAIN);
|
||||
DoCast(SPELL_RAY_OF_SUFFERING);
|
||||
events.ScheduleEvent(EVENT_OPTIC_LINK, 15000);
|
||||
events.ScheduleEvent(EVENT_CORROSIVE_SALIVA, 5000);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
@@ -93,48 +98,202 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (uiOpticLinkTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_OPTIC_LINK);
|
||||
uiOpticLinkTimer = 15000;
|
||||
} else uiOpticLinkTimer -= diff;
|
||||
events.Update(diff);
|
||||
|
||||
if (uiCorrosiveSalivaTimer <= diff)
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
DoCastVictim(SPELL_CORROSIVE_SALIVA);
|
||||
uiCorrosiveSalivaTimer = 10000;
|
||||
} else uiCorrosiveSalivaTimer -= diff;
|
||||
case EVENT_OPTIC_LINK:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(target, SPELL_OPTIC_LINK);
|
||||
events.ScheduleEvent(EVENT_OPTIC_LINK, 25000);
|
||||
break;
|
||||
case EVENT_CORROSIVE_SALIVA:
|
||||
DoCastVictim(SPELL_CORROSIVE_SALIVA);
|
||||
events.ScheduleEvent(EVENT_CORROSIVE_SALIVA, 10000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
{
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 7);
|
||||
}
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
{
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, DONE);
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 13);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap events;
|
||||
InstanceScript* instance;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<boss_moraggAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_moragg_ray_of_suffering : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_moragg_ray_of_suffering() : SpellScriptLoader("spell_moragg_ray_of_suffering") { }
|
||||
|
||||
class spell_moragg_ray_of_suffering_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_moragg_ray_of_suffering_AuraScript);
|
||||
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
std::list<HostileReference*> players = GetTarget()->getThreatManager().getThreatList();
|
||||
if (!players.empty())
|
||||
{
|
||||
std::list<HostileReference*>::iterator itr = players.begin();
|
||||
std::advance(itr, urand(0, players.size() - 1));
|
||||
|
||||
uint32 triggerSpell = GetSpellInfo()->GetEffect(aurEff->GetEffIndex())->TriggerSpell;
|
||||
GetTarget()->CastCustomSpell(triggerSpell, SPELLVALUE_MAX_TARGETS, 1, (*itr)->getTarget(), TRIGGERED_FULL_MASK, NULL, aurEff);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_moragg_ray_of_suffering_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_moragg_ray_of_suffering_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_moragg_ray_of_pain : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_moragg_ray_of_pain() : SpellScriptLoader("spell_moragg_ray_of_pain") { }
|
||||
|
||||
class spell_moragg_ray_of_pain_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_moragg_ray_of_pain_AuraScript);
|
||||
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
std::list<HostileReference*> players = GetTarget()->getThreatManager().getThreatList();
|
||||
if (!players.empty())
|
||||
{
|
||||
std::list<HostileReference*>::iterator itr = players.begin();
|
||||
std::advance(itr, urand(0, players.size() - 1));
|
||||
|
||||
uint32 triggerSpell = GetSpellInfo()->GetEffect(aurEff->GetEffIndex())->TriggerSpell;
|
||||
GetTarget()->CastCustomSpell(triggerSpell, SPELLVALUE_MAX_TARGETS, 1, (*itr)->getTarget(), TRIGGERED_FULL_MASK, NULL, aurEff);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_moragg_ray_of_pain_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_moragg_ray_of_pain_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_moragg_optic_link : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_moragg_optic_link() : SpellScriptLoader("spell_moragg_optic_link") { }
|
||||
|
||||
class spell_moragg_optic_link_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_moragg_optic_link_AuraScript);
|
||||
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
switch (aurEff->GetTickNumber()) // Different visual based on tick
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_1, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff);
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_1, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff);
|
||||
GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_2, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff);
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_1, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff);
|
||||
GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_2, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff);
|
||||
GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_3, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnUpdate(AuraEffect* aurEff)
|
||||
{
|
||||
switch (aurEff->GetTickNumber())
|
||||
{
|
||||
case 1:
|
||||
aurEff->SetAmount(aurEff->GetAmount() + 250); // base amount is 500
|
||||
break;
|
||||
case 4:
|
||||
aurEff->SetAmount(aurEff->GetAmount() * 2); // goes to 1500
|
||||
break;
|
||||
case 8:
|
||||
aurEff->SetAmount(aurEff->GetAmount() * 2); // goes to 3000
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_moragg_optic_link_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
|
||||
OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_moragg_optic_link_AuraScript::OnUpdate, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_moragg_optic_link_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_moragg()
|
||||
{
|
||||
new boss_moragg();
|
||||
new spell_moragg_ray_of_suffering();
|
||||
new spell_moragg_ray_of_pain();
|
||||
new spell_moragg_optic_link();
|
||||
}
|
||||
|
||||
@@ -17,24 +17,24 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "violet_hold.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellScript.h"
|
||||
#include "Player.h"
|
||||
#include "violet_hold.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_ARCANE_BARRAGE_VOLLEY = 54202,
|
||||
SPELL_ARCANE_BARRAGE_VOLLEY_H = 59483,
|
||||
SPELL_ARCANE_BUFFET = 54226,
|
||||
SPELL_ARCANE_BUFFET_H = 59485,
|
||||
SPELL_SUMMON_ETHEREAL_SPHERE_1 = 54102,
|
||||
SPELL_SUMMON_ETHEREAL_SPHERE_2 = 54137,
|
||||
SPELL_SUMMON_ETHEREAL_SPHERE_2 = 61337,
|
||||
SPELL_SUMMON_ETHEREAL_SPHERE_3 = 54138
|
||||
};
|
||||
|
||||
enum NPCs
|
||||
{
|
||||
NPC_ETHEREAL_SPHERE = 29271,
|
||||
//NPC_ETHEREAL_SPHERE2 = 32582, // heroic only?
|
||||
NPC_ETHEREAL_SPHERE2 = 32582
|
||||
};
|
||||
|
||||
enum CreatureSpells
|
||||
@@ -42,7 +42,8 @@ enum CreatureSpells
|
||||
SPELL_ARCANE_POWER = 54160,
|
||||
H_SPELL_ARCANE_POWER = 59474,
|
||||
SPELL_SUMMON_PLAYERS = 54164,
|
||||
SPELL_POWER_BALL_VISUAL = 54141
|
||||
SPELL_POWER_BALL_VISUAL = 54141,
|
||||
SPELL_POWER_BALL_DAMAGE_TRIGGER = 54207
|
||||
};
|
||||
|
||||
enum Yells
|
||||
@@ -56,52 +57,50 @@ enum Yells
|
||||
SAY_SUMMON_ENERGY = 6
|
||||
};
|
||||
|
||||
enum XevozzEvents
|
||||
{
|
||||
EVENT_ARCANE_BARRAGE = 1,
|
||||
EVENT_ARCANE_BUFFET,
|
||||
EVENT_SUMMON_SPHERE,
|
||||
EVENT_SUMMON_SPHERE_2,
|
||||
EVENT_RANGE_CHECK,
|
||||
EVENT_SUMMON_PLAYERS,
|
||||
EVENT_DESPAWN_SPHERE
|
||||
};
|
||||
|
||||
enum SphereActions
|
||||
{
|
||||
ACTION_SUMMON = 1,
|
||||
};
|
||||
|
||||
class boss_xevozz : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_xevozz() : CreatureScript("boss_xevozz") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<boss_xevozzAI>(creature);
|
||||
}
|
||||
|
||||
struct boss_xevozzAI : public ScriptedAI
|
||||
{
|
||||
boss_xevozzAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
uiSummonEtherealSphere_Timer = urand(10000, 12000);
|
||||
uiArcaneBarrageVolley_Timer = urand(20000, 22000);
|
||||
uiArcaneBuffet_Timer = uiSummonEtherealSphere_Timer + urand(5000, 6000);
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint32 uiSummonEtherealSphere_Timer;
|
||||
uint32 uiArcaneBarrageVolley_Timer;
|
||||
uint32 uiArcaneBuffet_Timer;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED);
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
|
||||
Initialize();
|
||||
DespawnSphere();
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
void DespawnSphere()
|
||||
{
|
||||
std::list<Creature*> assistList;
|
||||
GetCreatureListWithEntryInGrid(assistList, me, NPC_ETHEREAL_SPHERE, 150.0f);
|
||||
GetCreatureListWithEntryInGrid(assistList, me, NPC_ETHEREAL_SPHERE2, 150.0f);
|
||||
|
||||
if (assistList.empty())
|
||||
return;
|
||||
@@ -116,11 +115,7 @@ public:
|
||||
void JustSummoned(Creature* summoned) override
|
||||
{
|
||||
summoned->SetSpeed(MOVE_RUN, 0.5f);
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
{
|
||||
summoned->AddThreat(target, 0.00f);
|
||||
summoned->AI()->AttackStart(target);
|
||||
}
|
||||
summoned->GetMotionMaster()->MoveFollow(me, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
@@ -139,58 +134,23 @@ public:
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_XEVOZZ_CELL)))
|
||||
if (pDoor->GetGoState() == GO_STATE_READY)
|
||||
if (GameObject* door = instance->GetGameObject(DATA_XEVOZZ_CELL))
|
||||
if (door->GetGoState() == GO_STATE_READY)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
}
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
|
||||
void UpdateAI(uint32 uiDiff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (uiArcaneBarrageVolley_Timer < uiDiff)
|
||||
{
|
||||
DoCast(me, SPELL_ARCANE_BARRAGE_VOLLEY);
|
||||
uiArcaneBarrageVolley_Timer = urand(20000, 22000);
|
||||
}
|
||||
else uiArcaneBarrageVolley_Timer -= uiDiff;
|
||||
|
||||
if (uiArcaneBuffet_Timer)
|
||||
{
|
||||
if (uiArcaneBuffet_Timer < uiDiff)
|
||||
{
|
||||
DoCastVictim(SPELL_ARCANE_BUFFET);
|
||||
uiArcaneBuffet_Timer = 0;
|
||||
}
|
||||
else uiArcaneBuffet_Timer -= uiDiff;
|
||||
}
|
||||
|
||||
if (uiSummonEtherealSphere_Timer < uiDiff)
|
||||
{
|
||||
Talk(SAY_SPAWN);
|
||||
DoCast(me, SPELL_SUMMON_ETHEREAL_SPHERE_1);
|
||||
if (IsHeroic()) // extra one for heroic
|
||||
me->SummonCreature(NPC_ETHEREAL_SPHERE, me->GetPositionX() - 5 + rand32() % 10, me->GetPositionY() - 5 + rand32() % 10, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 40000);
|
||||
|
||||
uiSummonEtherealSphere_Timer = urand(45000, 47000);
|
||||
uiArcaneBuffet_Timer = urand(5000, 6000);
|
||||
}
|
||||
else uiSummonEtherealSphere_Timer -= uiDiff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
events.ScheduleEvent(EVENT_SUMMON_SPHERE, 5000);
|
||||
events.ScheduleEvent(EVENT_ARCANE_BARRAGE, urand(8000, 10000));
|
||||
events.ScheduleEvent(EVENT_ARCANE_BUFFET, urand(10000, 11000));
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -201,24 +161,86 @@ public:
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
{
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 7);
|
||||
}
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
{
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
instance->SetData(DATA_WAVE_COUNT, 13);
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() != TYPEID_PLAYER)
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* who, const SpellInfo* spell) override
|
||||
{
|
||||
if (!who->ToCreature())
|
||||
return;
|
||||
|
||||
Talk(SAY_SLAY);
|
||||
if ((spell->Id == SPELL_ARCANE_POWER) || (spell->Id == H_SPELL_ARCANE_POWER))
|
||||
Talk(SAY_SUMMON_ENERGY);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_ARCANE_BARRAGE:
|
||||
DoCast(SPELL_ARCANE_BARRAGE_VOLLEY);
|
||||
events.ScheduleEvent(EVENT_ARCANE_BARRAGE, urand(8000, 10000));
|
||||
break;
|
||||
case EVENT_ARCANE_BUFFET:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(target, SPELL_ARCANE_BUFFET);
|
||||
events.ScheduleEvent(EVENT_ARCANE_BUFFET, urand(15000, 20000));
|
||||
break;
|
||||
case EVENT_SUMMON_SPHERE:
|
||||
Talk(SAY_REPEAT_SUMMON);
|
||||
DoCast(SPELL_SUMMON_ETHEREAL_SPHERE_1);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_SUMMON_SPHERE_2, 2500);
|
||||
events.ScheduleEvent(EVENT_SUMMON_PLAYERS, urand(33000, 35000));
|
||||
events.ScheduleEvent(EVENT_SUMMON_SPHERE, urand(45000, 47000));
|
||||
break;
|
||||
case EVENT_SUMMON_SPHERE_2:
|
||||
Talk(SAY_REPEAT_SUMMON);
|
||||
DoCast(SPELL_SUMMON_ETHEREAL_SPHERE_2);
|
||||
break;
|
||||
case EVENT_SUMMON_PLAYERS:
|
||||
if (Creature* sphere = me->FindNearestCreature(NPC_ETHEREAL_SPHERE, 150.0f))
|
||||
sphere->GetAI()->DoAction(ACTION_SUMMON);
|
||||
else if (Creature* sphere = me->FindNearestCreature(NPC_ETHEREAL_SPHERE2, 150.0f))
|
||||
sphere->GetAI()->DoAction(ACTION_SUMMON);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<boss_xevozzAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_ethereal_sphere : public CreatureScript
|
||||
@@ -226,83 +248,149 @@ class npc_ethereal_sphere : public CreatureScript
|
||||
public:
|
||||
npc_ethereal_sphere() : CreatureScript("npc_ethereal_sphere") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_ethereal_sphereAI>(creature);
|
||||
}
|
||||
|
||||
struct npc_ethereal_sphereAI : public ScriptedAI
|
||||
{
|
||||
npc_ethereal_sphereAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
uiSummonPlayers_Timer = urand(33000, 35000);
|
||||
uiRangeCheck_Timer = 1000;
|
||||
arcanePower = false;
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint32 uiSummonPlayers_Timer;
|
||||
uint32 uiRangeCheck_Timer;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
events.Reset();
|
||||
DoCast(SPELL_POWER_BALL_VISUAL);
|
||||
DoCast(SPELL_POWER_BALL_DAMAGE_TRIGGER);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->setFaction(16);
|
||||
events.ScheduleEvent(EVENT_DESPAWN_SPHERE, 40000);
|
||||
events.ScheduleEvent(EVENT_RANGE_CHECK, 1000);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 uiDiff) override
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
if (action == ACTION_SUMMON)
|
||||
DoCast(SPELL_SUMMON_PLAYERS);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
if (!me->HasAura(SPELL_POWER_BALL_VISUAL))
|
||||
DoCast(me, SPELL_POWER_BALL_VISUAL);
|
||||
|
||||
if (uiRangeCheck_Timer < uiDiff)
|
||||
switch (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
if (Creature* pXevozz = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_XEVOZZ)))
|
||||
{
|
||||
float fDistance = me->GetDistance2d(pXevozz);
|
||||
if (fDistance <= 3)
|
||||
DoCast(pXevozz, SPELL_ARCANE_POWER);
|
||||
else
|
||||
DoCast(me, 35845); //Is it blizzlike?
|
||||
}
|
||||
uiRangeCheck_Timer = 1000;
|
||||
case EVENT_RANGE_CHECK:
|
||||
if (Creature* xevozz = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_XEVOZZ)))
|
||||
{
|
||||
if (me->IsWithinDist(xevozz, 3.0f) && !arcanePower)
|
||||
{
|
||||
DoCast(SPELL_ARCANE_POWER);
|
||||
arcanePower = true;
|
||||
events.ScheduleEvent(EVENT_DESPAWN_SPHERE, 8000);
|
||||
}
|
||||
}
|
||||
events.ScheduleEvent(EVENT_RANGE_CHECK, 1000);
|
||||
break;
|
||||
case EVENT_DESPAWN_SPHERE:
|
||||
me->DespawnOrUnsummon();
|
||||
break;
|
||||
}
|
||||
else uiRangeCheck_Timer -= uiDiff;
|
||||
}
|
||||
|
||||
if (uiSummonPlayers_Timer < uiDiff)
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
bool arcanePower;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_ethereal_sphereAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_xevozz_summon_players : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_xevozz_summon_players() : SpellScriptLoader("spell_xevozz_summon_players") { }
|
||||
|
||||
class spell_xevozz_summon_players_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_xevozz_summon_players_SpellScript);
|
||||
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* target = GetHitUnit();
|
||||
|
||||
if (target)
|
||||
{
|
||||
DoCast(me, SPELL_SUMMON_PLAYERS); // not working right
|
||||
Position pos = GetOriginalCaster()->GetPosition();
|
||||
|
||||
Map* map = me->GetMap();
|
||||
if (map && map->IsDungeon())
|
||||
{
|
||||
Map::PlayerList const &PlayerList = map->GetPlayers();
|
||||
|
||||
if (!PlayerList.isEmpty())
|
||||
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
|
||||
if (i->GetSource()->IsAlive())
|
||||
DoTeleportPlayer(i->GetSource(), me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), i->GetSource()->GetOrientation());
|
||||
}
|
||||
|
||||
uiSummonPlayers_Timer = urand(33000, 35000);
|
||||
target->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation());
|
||||
}
|
||||
else uiSummonPlayers_Timer -= uiDiff;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_xevozz_summon_players_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_xevozz_summon_players_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_xevozz_summon_ethereal_sphere : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_xevozz_summon_ethereal_sphere() : SpellScriptLoader("spell_xevozz_summon_ethereal_sphere") { }
|
||||
|
||||
class spell_xevozz_summon_ethereal_sphere_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_xevozz_summon_ethereal_sphere_SpellScript);
|
||||
|
||||
void HandleScript(SpellDestination& target)
|
||||
{
|
||||
Unit* caster = GetOriginalCaster();
|
||||
Position pos;
|
||||
float distance = 0.0f;
|
||||
|
||||
while (distance < 20.0f)
|
||||
{
|
||||
pos = caster->GetRandomNearPosition(60.0f);
|
||||
distance = caster->GetDistance(pos);
|
||||
}
|
||||
|
||||
target.Relocate(pos);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_xevozz_summon_ethereal_sphere_SpellScript::HandleScript, EFFECT_0, TARGET_DEST_DB);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_xevozz_summon_ethereal_sphere_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_xevozz()
|
||||
{
|
||||
new boss_xevozz();
|
||||
new npc_ethereal_sphere();
|
||||
new spell_xevozz_summon_players();
|
||||
new spell_xevozz_summon_ethereal_sphere();
|
||||
}
|
||||
|
||||
@@ -22,15 +22,9 @@
|
||||
enum Spells
|
||||
{
|
||||
SPELL_SHROUD_OF_DARKNESS = 54524,
|
||||
H_SPELL_SHROUD_OF_DARKNESS = 59745,
|
||||
SPELL_SUMMON_VOID_SENTRY = 54369,
|
||||
SPELL_VOID_SHIFT = 54361,
|
||||
H_SPELL_VOID_SHIFT = 59743,
|
||||
};
|
||||
|
||||
enum Creatures
|
||||
{
|
||||
NPC_VOID_SENTRY = 29364
|
||||
SPELL_VOID_SHIFTED = 54343,
|
||||
};
|
||||
|
||||
enum Yells
|
||||
@@ -48,19 +42,21 @@ enum Misc
|
||||
DATA_VOID_DANCE = 2153
|
||||
};
|
||||
|
||||
enum ZuramatEvents
|
||||
{
|
||||
EVENT_VOID_SHIFT = 1,
|
||||
EVENT_SUMMON_VOID,
|
||||
EVENT_SHROUD_OF_DARKNESS
|
||||
};
|
||||
|
||||
class boss_zuramat : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_zuramat() : CreatureScript("boss_zuramat") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<boss_zuramatAI>(creature);
|
||||
}
|
||||
|
||||
struct boss_zuramatAI : public ScriptedAI
|
||||
{
|
||||
boss_zuramatAI(Creature* creature) : ScriptedAI(creature)
|
||||
boss_zuramatAI(Creature* creature) : ScriptedAI(creature), sentries(me)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
@@ -68,18 +64,18 @@ public:
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
SpellShroudOfDarknessTimer = 22000;
|
||||
SpellVoidShiftTimer = 15000;
|
||||
SpellSummonVoidTimer = 12000;
|
||||
voidDance = true;
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint32 SpellVoidShiftTimer;
|
||||
uint32 SpellSummonVoidTimer;
|
||||
uint32 SpellShroudOfDarknessTimer;
|
||||
bool voidDance;
|
||||
void DespawnSentries()
|
||||
{
|
||||
sentries.DespawnAll();
|
||||
std::list<Creature*> sentrylist;
|
||||
GetCreatureListWithEntryInGrid(sentrylist, me, NPC_VOID_SENTRY_BALL, 200.0f);
|
||||
if (!sentrylist.empty())
|
||||
for (std::list<Creature*>::const_iterator itr = sentrylist.begin(); itr != sentrylist.end(); ++itr)
|
||||
(*itr)->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
@@ -89,6 +85,8 @@ public:
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
|
||||
Initialize();
|
||||
events.Reset();
|
||||
DespawnSentries();
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
@@ -107,48 +105,29 @@ public:
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_ZURAMAT_CELL)))
|
||||
if (pDoor->GetGoState() == GO_STATE_READY)
|
||||
if (GameObject* door = instance->GetGameObject(DATA_ZURAMAT_CELL))
|
||||
if (door->GetGoState() == GO_STATE_READY)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
|
||||
me->SetInCombatWithZone();
|
||||
events.ScheduleEvent(EVENT_SHROUD_OF_DARKNESS, urand(18000, 20000));
|
||||
events.ScheduleEvent(EVENT_VOID_SHIFT, 9000);
|
||||
events.ScheduleEvent(EVENT_SUMMON_VOID, 4000);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (SpellSummonVoidTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_SUMMON_VOID_SENTRY, false);
|
||||
SpellSummonVoidTimer = 20000;
|
||||
} else SpellSummonVoidTimer -=diff;
|
||||
|
||||
if (SpellVoidShiftTimer <= diff)
|
||||
{
|
||||
if (Unit* unit = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(unit, SPELL_VOID_SHIFT);
|
||||
SpellVoidShiftTimer = 20000;
|
||||
} else SpellVoidShiftTimer -=diff;
|
||||
|
||||
if (SpellShroudOfDarknessTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_SHROUD_OF_DARKNESS);
|
||||
SpellShroudOfDarknessTimer = 20000;
|
||||
} else SpellShroudOfDarknessTimer -=diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
sentries.Summon(summon);
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summoned, Unit* /*who*/) override
|
||||
@@ -167,29 +146,73 @@ public:
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SetData(DATA_ZURAMAT, 1);
|
||||
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
DespawnSentries();
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
{
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 7);
|
||||
}
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
{
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, DONE);
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 13);
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() != TYPEID_PLAYER)
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
Talk(SAY_SLAY);
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SUMMON_VOID:
|
||||
DoCast(SPELL_SUMMON_VOID_SENTRY);
|
||||
events.ScheduleEvent(EVENT_SUMMON_VOID, urand(7000, 10000));
|
||||
break;
|
||||
case EVENT_VOID_SHIFT:
|
||||
if (Unit* unit = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(unit, SPELL_VOID_SHIFT);
|
||||
events.ScheduleEvent(EVENT_VOID_SHIFT, 15000);
|
||||
break;
|
||||
case EVENT_SHROUD_OF_DARKNESS:
|
||||
DoCast(SPELL_SHROUD_OF_DARKNESS);
|
||||
events.ScheduleEvent(EVENT_SHROUD_OF_DARKNESS, urand(18000, 20000));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
SummonList sentries;
|
||||
bool voidDance;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<boss_zuramatAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class achievement_void_dance : public AchievementCriteriaScript
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
#include "Player.h"
|
||||
#include "TemporarySummon.h"
|
||||
|
||||
#define MAX_ENCOUNTER 3
|
||||
|
||||
/* Violet Hold encounters:
|
||||
0 - First boss
|
||||
1 - Second boss
|
||||
@@ -38,21 +36,6 @@
|
||||
6 - Zuramat
|
||||
7 - Cyanigosa */
|
||||
|
||||
enum GameObjects
|
||||
{
|
||||
GO_MAIN_DOOR = 191723,
|
||||
GO_XEVOZZ_DOOR = 191556,
|
||||
GO_LAVANTHOR_DOOR = 191566,
|
||||
GO_ICHORON_DOOR = 191722,
|
||||
GO_ZURAMAT_DOOR = 191565,
|
||||
GO_EREKEM_DOOR = 191564,
|
||||
GO_EREKEM_GUARD_1_DOOR = 191563,
|
||||
GO_EREKEM_GUARD_2_DOOR = 191562,
|
||||
GO_MORAGG_DOOR = 191606,
|
||||
GO_INTRO_ACTIVATION_CRYSTAL = 193615,
|
||||
GO_ACTIVATION_CRYSTAL = 193611
|
||||
};
|
||||
|
||||
enum AzureSaboteurSpells
|
||||
{
|
||||
SABOTEUR_SHIELD_DISRUPTION = 58291,
|
||||
@@ -64,7 +47,7 @@ enum CrystalSpells
|
||||
SPELL_ARCANE_LIGHTNING = 57930
|
||||
};
|
||||
|
||||
const Position PortalLocation[] =
|
||||
Position const PortalLocation[] =
|
||||
{
|
||||
{1877.51f, 850.104f, 44.6599f, 4.7822f }, // WP 1
|
||||
{1918.37f, 853.437f, 47.1624f, 4.12294f}, // WP 2
|
||||
@@ -74,21 +57,21 @@ const Position PortalLocation[] =
|
||||
{1908.31f, 809.657f, 38.7037f, 3.08701f} // WP 6
|
||||
};
|
||||
|
||||
const Position ArcaneSphere = {1887.060059f, 806.151001f, 61.321602f, 0.0f};
|
||||
const Position BossStartMove1 = {1894.684448f, 739.390503f, 47.668003f, 0.0f};
|
||||
const Position BossStartMove2 = {1875.173950f, 860.832703f, 43.333565f, 0.0f};
|
||||
const Position BossStartMove21 = {1858.854614f, 855.071411f, 43.333565f, 0.0f};
|
||||
const Position BossStartMove22 = {1891.926636f, 863.388977f, 43.333565f, 0.0f};
|
||||
const Position BossStartMove3 = {1916.138062f, 778.152222f, 35.772308f, 0.0f};
|
||||
const Position BossStartMove4 = {1853.618286f, 758.557617f, 38.657505f, 0.0f};
|
||||
const Position BossStartMove5 = {1906.683960f, 842.348022f, 38.637459f, 0.0f};
|
||||
const Position BossStartMove6 = {1928.207031f, 852.864441f, 47.200813f, 0.0f};
|
||||
Position const ArcaneSphere = {1887.060059f, 806.151001f, 61.321602f, 0.0f};
|
||||
Position const BossStartMove1 = {1894.684448f, 739.390503f, 47.668003f, 0.0f};
|
||||
Position const BossStartMove2 = {1875.173950f, 860.832703f, 43.333565f, 0.0f};
|
||||
Position const BossStartMove21 = {1858.854614f, 855.071411f, 43.333565f, 0.0f};
|
||||
Position const BossStartMove22 = {1891.926636f, 863.388977f, 43.333565f, 0.0f};
|
||||
Position const BossStartMove3 = {1916.138062f, 778.152222f, 35.772308f, 0.0f};
|
||||
Position const BossStartMove4 = {1853.618286f, 758.557617f, 38.657505f, 0.0f};
|
||||
Position const BossStartMove5 = {1906.683960f, 842.348022f, 38.637459f, 0.0f};
|
||||
Position const BossStartMove6 = {1928.207031f, 852.864441f, 47.200813f, 0.0f};
|
||||
|
||||
const Position CyanigosasSpawnLocation = {1930.281250f, 804.407715f, 52.410946f, 3.139621f};
|
||||
const Position MiddleRoomLocation = {1892.291260f, 805.696838f, 38.438862f, 3.139621f};
|
||||
const Position MiddleRoomPortalSaboLocation = {1896.622925f, 804.854126f, 38.504772f, 3.139621f};
|
||||
Position const CyanigosasSpawnLocation = {1930.281250f, 804.407715f, 52.410946f, 3.139621f};
|
||||
Position const MiddleRoomLocation = {1892.291260f, 805.696838f, 38.438862f, 3.139621f};
|
||||
Position const MiddleRoomPortalSaboLocation = {1896.622925f, 804.854126f, 38.504772f, 3.139621f};
|
||||
|
||||
//Cyanigosa's prefight event data
|
||||
// Cyanigosa's prefight event data
|
||||
enum Yells
|
||||
{
|
||||
CYANIGOSA_SAY_SPAWN = 0
|
||||
@@ -100,21 +83,45 @@ enum Spells
|
||||
CYANIGOSA_BLUE_AURA = 47759,
|
||||
};
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ NPC_XEVOZZ, DATA_XEVOZZ },
|
||||
{ NPC_LAVANTHOR, DATA_LAVANTHOR },
|
||||
{ NPC_ICHORON, DATA_ICHORON },
|
||||
{ NPC_ZURAMAT, DATA_ZURAMAT },
|
||||
{ NPC_EREKEM, DATA_EREKEM },
|
||||
{ NPC_MORAGG, DATA_MORAGG },
|
||||
{ NPC_CYANIGOSA, DATA_CYANIGOSA },
|
||||
{ NPC_SINCLARI, DATA_SINCLARI },
|
||||
{ 0, 0 } // END
|
||||
};
|
||||
|
||||
ObjectData const gameObjectData[] =
|
||||
{
|
||||
{ GO_EREKEM_GUARD_1_DOOR, DATA_EREKEM_LEFT_GUARD_CELL },
|
||||
{ GO_EREKEM_GUARD_2_DOOR, DATA_EREKEM_RIGHT_GUARD_CELL },
|
||||
{ GO_EREKEM_DOOR, DATA_EREKEM_CELL },
|
||||
{ GO_ZURAMAT_DOOR, DATA_ZURAMAT_CELL },
|
||||
{ GO_LAVANTHOR_DOOR, DATA_LAVANTHOR_CELL },
|
||||
{ GO_MORAGG_DOOR, DATA_MORAGG_CELL },
|
||||
{ GO_ICHORON_DOOR, DATA_ICHORON_CELL },
|
||||
{ GO_XEVOZZ_DOOR, DATA_XEVOZZ_CELL },
|
||||
{ GO_MAIN_DOOR, DATA_MAIN_DOOR },
|
||||
{ 0, 0 } // END
|
||||
};
|
||||
|
||||
class instance_violet_hold : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
instance_violet_hold() : InstanceMapScript("instance_violet_hold", 608) { }
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
{
|
||||
return new instance_violet_hold_InstanceMapScript(map);
|
||||
}
|
||||
|
||||
struct instance_violet_hold_InstanceMapScript : public InstanceScript
|
||||
{
|
||||
instance_violet_hold_InstanceMapScript(Map* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadObjectData(creatureData, gameObjectData);
|
||||
|
||||
uiRemoveNpc = 0;
|
||||
|
||||
@@ -138,29 +145,11 @@ public:
|
||||
bCrystalActivated = false;
|
||||
defenseless = true;
|
||||
uiMainEventPhase = NOT_STARTED;
|
||||
|
||||
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
|
||||
zuramatDead = false;
|
||||
}
|
||||
|
||||
ObjectGuid uiMoragg;
|
||||
ObjectGuid uiErekem;
|
||||
ObjectGuid uiErekemGuard[2];
|
||||
ObjectGuid uiIchoron;
|
||||
ObjectGuid uiLavanthor;
|
||||
ObjectGuid uiXevozz;
|
||||
ObjectGuid uiZuramat;
|
||||
ObjectGuid uiCyanigosa;
|
||||
ObjectGuid uiSinclari;
|
||||
|
||||
ObjectGuid uiMoraggCell;
|
||||
ObjectGuid uiErekemCell;
|
||||
ObjectGuid uiErekemLeftGuardCell;
|
||||
ObjectGuid uiErekemRightGuardCell;
|
||||
ObjectGuid uiIchoronCell;
|
||||
ObjectGuid uiLavanthorCell;
|
||||
ObjectGuid uiXevozzCell;
|
||||
ObjectGuid uiZuramatCell;
|
||||
ObjectGuid uiMainDoor;
|
||||
ObjectGuid uiTeleportationPortal;
|
||||
ObjectGuid uiSaboteurPortal;
|
||||
|
||||
@@ -180,7 +169,6 @@ public:
|
||||
|
||||
uint8 uiDoorIntegrity;
|
||||
|
||||
uint16 m_auiEncounter[MAX_ENCOUNTER];
|
||||
uint8 uiCountErekemGuards;
|
||||
uint8 uiCountActivationCrystals;
|
||||
uint8 uiCyanigosaEventPhase;
|
||||
@@ -191,132 +179,93 @@ public:
|
||||
bool bIsDoorSpellCast;
|
||||
bool bCrystalActivated;
|
||||
bool defenseless;
|
||||
bool zuramatDead;
|
||||
|
||||
std::list<uint8> NpcAtDoorCastingList;
|
||||
|
||||
std::string str_data;
|
||||
|
||||
bool IsEncounterInProgress() const override
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
|
||||
if (m_auiEncounter[i] == IN_PROGRESS)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case CREATURE_XEVOZZ:
|
||||
uiXevozz = creature->GetGUID();
|
||||
break;
|
||||
case CREATURE_LAVANTHOR:
|
||||
uiLavanthor = creature->GetGUID();
|
||||
break;
|
||||
case CREATURE_ICHORON:
|
||||
uiIchoron = creature->GetGUID();
|
||||
break;
|
||||
case CREATURE_ZURAMAT:
|
||||
uiZuramat = creature->GetGUID();
|
||||
break;
|
||||
case CREATURE_EREKEM:
|
||||
uiErekem = creature->GetGUID();
|
||||
break;
|
||||
case CREATURE_EREKEM_GUARD:
|
||||
case NPC_EREKEM_GUARD:
|
||||
if (uiCountErekemGuards < 2)
|
||||
{
|
||||
uiErekemGuard[uiCountErekemGuards++] = creature->GetGUID();
|
||||
creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
|
||||
creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE);
|
||||
}
|
||||
break;
|
||||
case CREATURE_MORAGG:
|
||||
uiMoragg = creature->GetGUID();
|
||||
case NPC_CYANIGOSA:
|
||||
creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE);
|
||||
break;
|
||||
case CREATURE_CYANIGOSA:
|
||||
uiCyanigosa = creature->GetGUID();
|
||||
creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
|
||||
default:
|
||||
break;
|
||||
case CREATURE_SINCLARI:
|
||||
uiSinclari = creature->GetGUID();
|
||||
case NPC_VOID_SENTRY:
|
||||
if (zuramatDead)
|
||||
{
|
||||
creature->DespawnOrUnsummon();
|
||||
zuramatDead = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
BEWARE - SHIT.
|
||||
if (creature->GetGUID() == uiFirstBoss || creature->GetGUID() == uiSecondBoss)
|
||||
/*if (creature->GetGUID() == uiFirstBoss || creature->GetGUID() == uiSecondBoss)
|
||||
{
|
||||
creature->AllLootRemovedFromCorpse();
|
||||
creature->RemoveLootMode(1);
|
||||
}
|
||||
*/
|
||||
}*/
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* go) override
|
||||
{
|
||||
InstanceScript::OnGameObjectCreate(go);
|
||||
|
||||
switch (go->GetEntry())
|
||||
{
|
||||
case GO_EREKEM_GUARD_1_DOOR:
|
||||
uiErekemLeftGuardCell = go->GetGUID();
|
||||
break;
|
||||
case GO_EREKEM_GUARD_2_DOOR:
|
||||
uiErekemRightGuardCell = go->GetGUID();
|
||||
break;
|
||||
case GO_EREKEM_DOOR:
|
||||
uiErekemCell = go->GetGUID();
|
||||
break;
|
||||
case GO_ZURAMAT_DOOR:
|
||||
uiZuramatCell = go->GetGUID();
|
||||
break;
|
||||
case GO_LAVANTHOR_DOOR:
|
||||
uiLavanthorCell = go->GetGUID();
|
||||
break;
|
||||
case GO_MORAGG_DOOR:
|
||||
uiMoraggCell = go->GetGUID();
|
||||
break;
|
||||
case GO_ICHORON_DOOR:
|
||||
uiIchoronCell = go->GetGUID();
|
||||
break;
|
||||
case GO_XEVOZZ_DOOR:
|
||||
uiXevozzCell = go->GetGUID();
|
||||
break;
|
||||
case GO_MAIN_DOOR:
|
||||
uiMainDoor = go->GetGUID();
|
||||
break;
|
||||
case GO_ACTIVATION_CRYSTAL:
|
||||
if (uiCountActivationCrystals < 4)
|
||||
uiActivationCrystal[uiCountActivationCrystals++] = go->GetGUID();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool SetBossState(uint32 type, EncounterState state) override
|
||||
{
|
||||
if (!InstanceScript::SetBossState(type, state))
|
||||
return false;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DATA_1ST_BOSS_EVENT:
|
||||
if (state == DONE)
|
||||
UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, NPC_EREKEM, nullptr);
|
||||
break;
|
||||
case DATA_2ND_BOSS_EVENT:
|
||||
if (state == DONE)
|
||||
UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, NPC_MORAGG, nullptr);
|
||||
break;
|
||||
case DATA_CYANIGOSA:
|
||||
if (state == DONE)
|
||||
{
|
||||
uiMainEventPhase = DONE;
|
||||
if (GameObject* mainDoor = GetGameObject(DATA_MAIN_DOOR))
|
||||
mainDoor->SetGoState(GO_STATE_ACTIVE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_1ST_BOSS_EVENT:
|
||||
UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, CREATURE_EREKEM, NULL);
|
||||
m_auiEncounter[0] = data;
|
||||
if (data == DONE)
|
||||
SaveToDB();
|
||||
break;
|
||||
case DATA_2ND_BOSS_EVENT:
|
||||
UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, CREATURE_MORAGG, NULL);
|
||||
m_auiEncounter[1] = data;
|
||||
if (data == DONE)
|
||||
SaveToDB();
|
||||
break;
|
||||
case DATA_CYANIGOSA_EVENT:
|
||||
m_auiEncounter[2] = data;
|
||||
if (data == DONE)
|
||||
{
|
||||
SaveToDB();
|
||||
uiMainEventPhase = DONE;
|
||||
if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor))
|
||||
pMainDoor->SetGoState(GO_STATE_ACTIVE);
|
||||
}
|
||||
break;
|
||||
case DATA_WAVE_COUNT:
|
||||
uiWaveCount = data;
|
||||
bActive = true;
|
||||
@@ -340,21 +289,8 @@ public:
|
||||
NpcAtDoorCastingList.pop_back();
|
||||
break;
|
||||
case DATA_MAIN_DOOR:
|
||||
if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor))
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case GO_STATE_ACTIVE:
|
||||
pMainDoor->SetGoState(GO_STATE_ACTIVE);
|
||||
break;
|
||||
case GO_STATE_READY:
|
||||
pMainDoor->SetGoState(GO_STATE_READY);
|
||||
break;
|
||||
case GO_STATE_ACTIVE_ALTERNATIVE:
|
||||
pMainDoor->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (GameObject* mainDoor = GetGameObject(type))
|
||||
mainDoor->SetGoState(GOState(data));
|
||||
break;
|
||||
case DATA_START_BOSS_ENCOUNTER:
|
||||
switch (uiWaveCount)
|
||||
@@ -374,7 +310,7 @@ public:
|
||||
uiMainEventPhase = data;
|
||||
if (data == IN_PROGRESS) // Start event
|
||||
{
|
||||
if (GameObject* mainDoor = instance->GetGameObject(uiMainDoor))
|
||||
if (GameObject* mainDoor = GetGameObject(DATA_MAIN_DOOR))
|
||||
mainDoor->SetGoState(GO_STATE_READY);
|
||||
uiWaveCount = 1;
|
||||
bActive = true;
|
||||
@@ -384,6 +320,9 @@ public:
|
||||
uiRemoveNpc = 0; // might not have been reset after a wipe on a boss.
|
||||
}
|
||||
break;
|
||||
case DATA_ZURAMAT:
|
||||
zuramatDead = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,9 +343,6 @@ public:
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_1ST_BOSS_EVENT: return m_auiEncounter[0];
|
||||
case DATA_2ND_BOSS_EVENT: return m_auiEncounter[1];
|
||||
case DATA_CYANIGOSA_EVENT: return m_auiEncounter[2];
|
||||
case DATA_WAVE_COUNT: return uiWaveCount;
|
||||
case DATA_REMOVE_NPC: return uiRemoveNpc;
|
||||
case DATA_PORTAL_LOCATION: return uiLocation;
|
||||
@@ -421,125 +357,114 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
ObjectGuid GetGuidData(uint32 identifier) const override
|
||||
ObjectGuid GetGuidData(uint32 type) const override
|
||||
{
|
||||
switch (identifier)
|
||||
switch (type)
|
||||
{
|
||||
case DATA_MORAGG: return uiMoragg;
|
||||
case DATA_EREKEM: return uiErekem;
|
||||
case DATA_EREKEM_GUARD_1: return uiErekemGuard[0];
|
||||
case DATA_EREKEM_GUARD_2: return uiErekemGuard[1];
|
||||
case DATA_ICHORON: return uiIchoron;
|
||||
case DATA_LAVANTHOR: return uiLavanthor;
|
||||
case DATA_XEVOZZ: return uiXevozz;
|
||||
case DATA_ZURAMAT: return uiZuramat;
|
||||
case DATA_CYANIGOSA: return uiCyanigosa;
|
||||
case DATA_MORAGG_CELL: return uiMoraggCell;
|
||||
case DATA_EREKEM_CELL: return uiErekemCell;
|
||||
case DATA_EREKEM_RIGHT_GUARD_CELL: return uiErekemRightGuardCell;
|
||||
case DATA_EREKEM_LEFT_GUARD_CELL: return uiErekemLeftGuardCell;
|
||||
case DATA_ICHORON_CELL: return uiIchoronCell;
|
||||
case DATA_LAVANTHOR_CELL: return uiLavanthorCell;
|
||||
case DATA_XEVOZZ_CELL: return uiXevozzCell;
|
||||
case DATA_ZURAMAT_CELL: return uiZuramatCell;
|
||||
case DATA_MAIN_DOOR: return uiMainDoor;
|
||||
case DATA_SINCLARI: return uiSinclari;
|
||||
case DATA_TELEPORTATION_PORTAL: return uiTeleportationPortal;
|
||||
case DATA_SABOTEUR_PORTAL: return uiSaboteurPortal;
|
||||
}
|
||||
|
||||
return ObjectGuid::Empty;
|
||||
return InstanceScript::GetGuidData(type);
|
||||
}
|
||||
|
||||
void SpawnPortal()
|
||||
{
|
||||
SetData(DATA_PORTAL_LOCATION, (GetData(DATA_PORTAL_LOCATION) + urand(1, 5))%6);
|
||||
if (Creature* pSinclari = instance->GetCreature(uiSinclari))
|
||||
if (Creature* portal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL, PortalLocation[GetData(DATA_PORTAL_LOCATION)], TEMPSUMMON_CORPSE_DESPAWN))
|
||||
if (Creature* sinclari = GetCreature(DATA_SINCLARI))
|
||||
if (Creature* portal = sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, PortalLocation[GetData(DATA_PORTAL_LOCATION)], TEMPSUMMON_CORPSE_DESPAWN))
|
||||
uiTeleportationPortal = portal->GetGUID();
|
||||
}
|
||||
|
||||
void StartBossEncounter(uint8 uiBoss, bool bForceRespawn = true)
|
||||
{
|
||||
Creature* pBoss = NULL;
|
||||
Creature* boss = nullptr;
|
||||
|
||||
switch (uiBoss)
|
||||
{
|
||||
case BOSS_MORAGG:
|
||||
HandleGameObject(uiMoraggCell, bForceRespawn);
|
||||
pBoss = instance->GetCreature(uiMoragg);
|
||||
if (pBoss)
|
||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove1);
|
||||
HandleGameObject(GetObjectGuid(DATA_MORAGG_CELL), bForceRespawn);
|
||||
boss = GetCreature(DATA_MORAGG);
|
||||
if (boss)
|
||||
boss->GetMotionMaster()->MovePoint(0, BossStartMove1);
|
||||
break;
|
||||
case BOSS_EREKEM:
|
||||
HandleGameObject(uiErekemCell, bForceRespawn);
|
||||
HandleGameObject(uiErekemRightGuardCell, bForceRespawn);
|
||||
HandleGameObject(uiErekemLeftGuardCell, bForceRespawn);
|
||||
HandleGameObject(GetObjectGuid(DATA_EREKEM_CELL), bForceRespawn);
|
||||
HandleGameObject(GetObjectGuid(DATA_EREKEM_LEFT_GUARD_CELL), bForceRespawn);
|
||||
HandleGameObject(GetObjectGuid(DATA_EREKEM_RIGHT_GUARD_CELL), bForceRespawn);
|
||||
|
||||
pBoss = instance->GetCreature(uiErekem);
|
||||
|
||||
if (pBoss)
|
||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove2);
|
||||
boss = GetCreature(DATA_EREKEM);
|
||||
if (boss)
|
||||
boss->GetMotionMaster()->MovePoint(0, BossStartMove2);
|
||||
|
||||
if (Creature* pGuard1 = instance->GetCreature(uiErekemGuard[0]))
|
||||
{
|
||||
if (bForceRespawn)
|
||||
pGuard1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
|
||||
{
|
||||
pGuard1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE);
|
||||
pGuard1->GetMotionMaster()->MovePoint(0, BossStartMove21);
|
||||
}
|
||||
else
|
||||
pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
|
||||
pGuard1->GetMotionMaster()->MovePoint(0, BossStartMove21);
|
||||
}
|
||||
|
||||
if (Creature* pGuard2 = instance->GetCreature(uiErekemGuard[1]))
|
||||
{
|
||||
if (bForceRespawn)
|
||||
{
|
||||
pGuard2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
|
||||
pGuard2->GetMotionMaster()->MovePoint(0, BossStartMove22);
|
||||
}
|
||||
else
|
||||
pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
|
||||
pGuard2->GetMotionMaster()->MovePoint(0, BossStartMove22);
|
||||
}
|
||||
break;
|
||||
case BOSS_ICHORON:
|
||||
HandleGameObject(uiIchoronCell, bForceRespawn);
|
||||
pBoss = instance->GetCreature(uiIchoron);
|
||||
if (pBoss)
|
||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove3);
|
||||
HandleGameObject(GetObjectGuid(DATA_ICHORON_CELL), bForceRespawn);
|
||||
boss = GetCreature(DATA_ICHORON);
|
||||
if (boss)
|
||||
boss->GetMotionMaster()->MovePoint(0, BossStartMove3);
|
||||
break;
|
||||
case BOSS_LAVANTHOR:
|
||||
HandleGameObject(uiLavanthorCell, bForceRespawn);
|
||||
pBoss = instance->GetCreature(uiLavanthor);
|
||||
if (pBoss)
|
||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove4);
|
||||
HandleGameObject(GetObjectGuid(DATA_LAVANTHOR_CELL), bForceRespawn);
|
||||
boss = GetCreature(DATA_LAVANTHOR);
|
||||
if (boss)
|
||||
boss->GetMotionMaster()->MovePoint(0, BossStartMove4);
|
||||
break;
|
||||
case BOSS_XEVOZZ:
|
||||
HandleGameObject(uiXevozzCell, bForceRespawn);
|
||||
pBoss = instance->GetCreature(uiXevozz);
|
||||
if (pBoss)
|
||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove5);
|
||||
HandleGameObject(GetObjectGuid(DATA_XEVOZZ_CELL), bForceRespawn);
|
||||
boss = GetCreature(DATA_XEVOZZ);
|
||||
if (boss)
|
||||
boss->GetMotionMaster()->MovePoint(0, BossStartMove5);
|
||||
break;
|
||||
case BOSS_ZURAMAT:
|
||||
HandleGameObject(uiZuramatCell, bForceRespawn);
|
||||
pBoss = instance->GetCreature(uiZuramat);
|
||||
if (pBoss)
|
||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove6);
|
||||
HandleGameObject(GetObjectGuid(DATA_ZURAMAT_CELL), bForceRespawn);
|
||||
boss = GetCreature(DATA_ZURAMAT);
|
||||
if (boss)
|
||||
boss->GetMotionMaster()->MovePoint(0, BossStartMove6);
|
||||
break;
|
||||
}
|
||||
|
||||
// generic boss state changes
|
||||
if (pBoss)
|
||||
if (boss)
|
||||
{
|
||||
pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
|
||||
pBoss->SetReactState(REACT_AGGRESSIVE);
|
||||
boss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
|
||||
boss->SetReactState(REACT_AGGRESSIVE);
|
||||
|
||||
if (!bForceRespawn)
|
||||
{
|
||||
if (pBoss->isDead())
|
||||
if (boss->isDead())
|
||||
{
|
||||
// respawn but avoid to be looted again
|
||||
pBoss->Respawn();
|
||||
pBoss->RemoveLootMode(1);
|
||||
boss->Respawn();
|
||||
boss->RemoveLootMode(1);
|
||||
}
|
||||
pBoss->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
|
||||
else
|
||||
boss->GetMotionMaster()->MoveTargetedHome();
|
||||
|
||||
boss->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
|
||||
uiWaveCount = 0;
|
||||
}
|
||||
}
|
||||
@@ -555,12 +480,12 @@ public:
|
||||
case 6:
|
||||
if (uiFirstBoss == 0)
|
||||
uiFirstBoss = urand(1, 6);
|
||||
if (Creature* pSinclari = instance->GetCreature(uiSinclari))
|
||||
if (Creature* sinclari = GetCreature(DATA_SINCLARI))
|
||||
{
|
||||
if (Creature* pPortal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN))
|
||||
uiSaboteurPortal = pPortal->GetGUID();
|
||||
if (Creature* pAzureSaboteur = pSinclari->SummonCreature(CREATURE_SABOTEOUR, MiddleRoomLocation, TEMPSUMMON_DEAD_DESPAWN))
|
||||
pAzureSaboteur->CastSpell(pAzureSaboteur, SABOTEUR_SHIELD_EFFECT, false);
|
||||
if (Creature* portal = sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN))
|
||||
uiSaboteurPortal = portal->GetGUID();
|
||||
if (Creature* azureSaboteur = sinclari->SummonCreature(NPC_SABOTEOUR, MiddleRoomLocation, TEMPSUMMON_DEAD_DESPAWN))
|
||||
azureSaboteur->CastSpell(azureSaboteur, SABOTEUR_SHIELD_EFFECT, false);
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
@@ -569,25 +494,22 @@ public:
|
||||
{
|
||||
uiSecondBoss = urand(1, 6);
|
||||
} while (uiSecondBoss == uiFirstBoss);
|
||||
if (Creature* pSinclari = instance->GetCreature(uiSinclari))
|
||||
if (Creature* sinclari = GetCreature(DATA_SINCLARI))
|
||||
{
|
||||
if (Creature* pPortal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN))
|
||||
if (Creature* pPortal = sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN))
|
||||
uiSaboteurPortal = pPortal->GetGUID();
|
||||
if (Creature* pAzureSaboteur = pSinclari->SummonCreature(CREATURE_SABOTEOUR, MiddleRoomLocation, TEMPSUMMON_DEAD_DESPAWN))
|
||||
if (Creature* pAzureSaboteur = sinclari->SummonCreature(NPC_SABOTEOUR, MiddleRoomLocation, TEMPSUMMON_DEAD_DESPAWN))
|
||||
pAzureSaboteur->CastSpell(pAzureSaboteur, SABOTEUR_SHIELD_EFFECT, false);
|
||||
}
|
||||
break;
|
||||
case 18:
|
||||
{
|
||||
Creature* pSinclari = instance->GetCreature(uiSinclari);
|
||||
if (pSinclari)
|
||||
pSinclari->SummonCreature(CREATURE_CYANIGOSA, CyanigosasSpawnLocation, TEMPSUMMON_DEAD_DESPAWN);
|
||||
if (Creature* sinclari = GetCreature(DATA_SINCLARI))
|
||||
sinclari->SummonCreature(NPC_CYANIGOSA, CyanigosasSpawnLocation, TEMPSUMMON_DEAD_DESPAWN);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor))
|
||||
pMainDoor->SetGoState(GO_STATE_READY);
|
||||
if (GameObject* mainDoor = GetGameObject(DATA_MAIN_DOOR))
|
||||
mainDoor->SetGoState(GO_STATE_READY);
|
||||
DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, 100);
|
||||
// no break
|
||||
}
|
||||
@@ -597,54 +519,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetSaveData() override
|
||||
void WriteSaveDataMore(std::ostringstream& data) override
|
||||
{
|
||||
OUT_SAVE_INST_DATA;
|
||||
|
||||
std::ostringstream saveStream;
|
||||
saveStream << "V H " << (uint16)m_auiEncounter[0]
|
||||
<< ' ' << (uint16)m_auiEncounter[1]
|
||||
<< ' ' << (uint16)m_auiEncounter[2]
|
||||
<< ' ' << (uint16)uiFirstBoss
|
||||
<< ' ' << (uint16)uiSecondBoss;
|
||||
|
||||
str_data = saveStream.str();
|
||||
|
||||
OUT_SAVE_INST_DATA_COMPLETE;
|
||||
return str_data;
|
||||
data << uiFirstBoss << ' ' << uiSecondBoss;
|
||||
}
|
||||
|
||||
void Load(const char* in) override
|
||||
void ReadSaveDataMore(std::istringstream& data) override
|
||||
{
|
||||
if (!in)
|
||||
{
|
||||
OUT_LOAD_INST_DATA_FAIL;
|
||||
return;
|
||||
}
|
||||
|
||||
OUT_LOAD_INST_DATA(in);
|
||||
|
||||
char dataHead1, dataHead2;
|
||||
uint16 data0, data1, data2, data3, data4;
|
||||
|
||||
std::istringstream loadStream(in);
|
||||
loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4;
|
||||
|
||||
if (dataHead1 == 'V' && dataHead2 == 'H')
|
||||
{
|
||||
m_auiEncounter[0] = data0;
|
||||
m_auiEncounter[1] = data1;
|
||||
m_auiEncounter[2] = data2;
|
||||
|
||||
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
|
||||
if (m_auiEncounter[i] == IN_PROGRESS)
|
||||
m_auiEncounter[i] = NOT_STARTED;
|
||||
|
||||
uiFirstBoss = uint8(data3);
|
||||
uiSecondBoss = uint8(data4);
|
||||
} else OUT_LOAD_INST_DATA_FAIL;
|
||||
|
||||
OUT_LOAD_INST_DATA_COMPLETE;
|
||||
data >> uiFirstBoss;
|
||||
data >> uiSecondBoss;
|
||||
}
|
||||
|
||||
bool CheckWipe()
|
||||
@@ -660,6 +543,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
zuramatDead = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -690,59 +574,57 @@ public:
|
||||
SetData(DATA_MAIN_DOOR, GO_STATE_ACTIVE);
|
||||
SetData(DATA_WAVE_COUNT, 0);
|
||||
uiMainEventPhase = NOT_STARTED;
|
||||
uiActivationTimer = 5000;
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
if (GameObject* crystal = instance->GetGameObject(uiActivationCrystal[i]))
|
||||
crystal->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||
|
||||
if (Creature* pSinclari = instance->GetCreature(uiSinclari))
|
||||
if (Creature* sinclari = GetCreature(DATA_SINCLARI))
|
||||
{
|
||||
pSinclari->SetVisible(true);
|
||||
sinclari->SetVisible(true);
|
||||
|
||||
std::list<Creature*> GuardList;
|
||||
pSinclari->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f);
|
||||
sinclari->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f);
|
||||
if (!GuardList.empty())
|
||||
{
|
||||
for (std::list<Creature*>::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr)
|
||||
for (Creature* guard : GuardList)
|
||||
{
|
||||
if (Creature* pGuard = *itr)
|
||||
{
|
||||
pGuard->SetVisible(true);
|
||||
pGuard->SetReactState(REACT_AGGRESSIVE);
|
||||
pGuard->GetMotionMaster()->MovePoint(1, pGuard->GetHomePosition());
|
||||
}
|
||||
guard->SetVisible(true);
|
||||
guard->SetReactState(REACT_AGGRESSIVE);
|
||||
guard->GetMotionMaster()->MovePoint(1, guard->GetHomePosition());
|
||||
}
|
||||
}
|
||||
pSinclari->GetMotionMaster()->MovePoint(1, pSinclari->GetHomePosition());
|
||||
pSinclari->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
sinclari->GetMotionMaster()->MovePoint(1, sinclari->GetHomePosition());
|
||||
sinclari->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
}
|
||||
|
||||
// Cyanigosa is spawned but not tranformed, prefight event
|
||||
Creature* pCyanigosa = instance->GetCreature(uiCyanigosa);
|
||||
if (pCyanigosa && !pCyanigosa->HasAura(CYANIGOSA_SPELL_TRANSFORM))
|
||||
Creature* cyanigosa = GetCreature(DATA_CYANIGOSA);
|
||||
if (cyanigosa && !cyanigosa->HasAura(CYANIGOSA_SPELL_TRANSFORM))
|
||||
{
|
||||
if (uiCyanigosaEventTimer <= diff)
|
||||
{
|
||||
switch (uiCyanigosaEventPhase)
|
||||
{
|
||||
case 1:
|
||||
pCyanigosa->CastSpell(pCyanigosa, CYANIGOSA_BLUE_AURA, false);
|
||||
pCyanigosa->AI()->Talk(CYANIGOSA_SAY_SPAWN);
|
||||
cyanigosa->CastSpell(cyanigosa, CYANIGOSA_BLUE_AURA, false);
|
||||
cyanigosa->AI()->Talk(CYANIGOSA_SAY_SPAWN);
|
||||
uiCyanigosaEventTimer = 7*IN_MILLISECONDS;
|
||||
++uiCyanigosaEventPhase;
|
||||
break;
|
||||
case 2:
|
||||
pCyanigosa->GetMotionMaster()->MoveJump(MiddleRoomLocation.GetPositionX(), MiddleRoomLocation.GetPositionY(), MiddleRoomLocation.GetPositionZ(), 10.0f, 20.0f);
|
||||
pCyanigosa->CastSpell(pCyanigosa, CYANIGOSA_BLUE_AURA, false);
|
||||
cyanigosa->GetMotionMaster()->MoveJump(MiddleRoomLocation.GetPositionX(), MiddleRoomLocation.GetPositionY(), MiddleRoomLocation.GetPositionZ(), 10.0f, 20.0f);
|
||||
cyanigosa->CastSpell(cyanigosa, CYANIGOSA_BLUE_AURA, false);
|
||||
uiCyanigosaEventTimer = 7*IN_MILLISECONDS;
|
||||
++uiCyanigosaEventPhase;
|
||||
break;
|
||||
case 3:
|
||||
pCyanigosa->RemoveAurasDueToSpell(CYANIGOSA_BLUE_AURA);
|
||||
pCyanigosa->CastSpell(pCyanigosa, CYANIGOSA_SPELL_TRANSFORM, 0);
|
||||
pCyanigosa->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
|
||||
pCyanigosa->SetReactState(REACT_AGGRESSIVE);
|
||||
cyanigosa->RemoveAurasDueToSpell(CYANIGOSA_BLUE_AURA);
|
||||
cyanigosa->CastSpell(cyanigosa, CYANIGOSA_SPELL_TRANSFORM, 0);
|
||||
cyanigosa->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
|
||||
cyanigosa->SetReactState(REACT_AGGRESSIVE);
|
||||
uiCyanigosaEventTimer = 2*IN_MILLISECONDS;
|
||||
++uiCyanigosaEventPhase;
|
||||
break;
|
||||
@@ -815,6 +697,11 @@ public:
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
{
|
||||
return new instance_violet_hold_InstanceMapScript(map);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_violet_hold()
|
||||
|
||||
@@ -28,22 +28,23 @@
|
||||
#define GOSSIP_START_EVENT "Get your people to safety, we'll keep the Blue Dragonflight's forces at bay."
|
||||
#define GOSSIP_ITEM_1 "Activate the crystals when we get in trouble, right"
|
||||
#define GOSSIP_I_WANT_IN "I'm not fighting, so send me in now!"
|
||||
#define SAY_EVENT_LOCK "I'm locking the door. Good luck, and thank you for doing this."
|
||||
#define SPAWN_TIME 20000
|
||||
|
||||
enum PortalCreatures
|
||||
{
|
||||
CREATURE_AZURE_INVADER_1 = 30661,
|
||||
CREATURE_AZURE_INVADER_2 = 30961,
|
||||
CREATURE_AZURE_SPELLBREAKER_1 = 30662,
|
||||
CREATURE_AZURE_SPELLBREAKER_2 = 30962,
|
||||
CREATURE_AZURE_BINDER_1 = 30663,
|
||||
CREATURE_AZURE_BINDER_2 = 30918,
|
||||
CREATURE_AZURE_MAGE_SLAYER_1 = 30664,
|
||||
CREATURE_AZURE_MAGE_SLAYER_2 = 30963,
|
||||
CREATURE_AZURE_CAPTAIN = 30666,
|
||||
CREATURE_AZURE_SORCEROR = 30667,
|
||||
CREATURE_AZURE_RAIDER = 30668,
|
||||
CREATURE_AZURE_STALKER = 32191
|
||||
NPC_AZURE_INVADER_1 = 30661,
|
||||
NPC_AZURE_INVADER_2 = 30961,
|
||||
NPC_AZURE_SPELLBREAKER_1 = 30662,
|
||||
NPC_AZURE_SPELLBREAKER_2 = 30962,
|
||||
NPC_AZURE_BINDER_1 = 30663,
|
||||
NPC_AZURE_BINDER_2 = 30918,
|
||||
NPC_AZURE_MAGE_SLAYER_1 = 30664,
|
||||
NPC_AZURE_MAGE_SLAYER_2 = 30963,
|
||||
NPC_AZURE_CAPTAIN = 30666,
|
||||
NPC_AZURE_SORCEROR = 30667,
|
||||
NPC_AZURE_RAIDER = 30668,
|
||||
NPC_AZURE_STALKER = 32191
|
||||
};
|
||||
|
||||
enum AzureInvaderSpells
|
||||
@@ -59,7 +60,7 @@ enum AzureSellbreakerSpells
|
||||
SPELL_ARCANE_BLAST = 58462,
|
||||
SPELL_SLOW = 25603,
|
||||
SPELL_CHAINS_OF_ICE = 58464,
|
||||
SPELL_CONE_OF_COLD = 58463
|
||||
SPELL_CONE_OF_COLD = 58463,
|
||||
};
|
||||
|
||||
enum AzureBinderSpells
|
||||
@@ -67,7 +68,7 @@ enum AzureBinderSpells
|
||||
SPELL_ARCANE_BARRAGE = 58456,
|
||||
SPELL_ARCANE_EXPLOSION = 58455,
|
||||
SPELL_FROST_NOVA = 58458,
|
||||
SPELL_FROSTBOLT = 58457
|
||||
SPELL_FROSTBOLT = 58457,
|
||||
};
|
||||
|
||||
enum AzureMageSlayerSpells
|
||||
@@ -85,7 +86,7 @@ enum AzureCaptainSpells
|
||||
enum AzureSorcerorSpells
|
||||
{
|
||||
SPELL_ARCANE_STREAM = 60181,
|
||||
SPELL_MANA_DETONATION = 60182
|
||||
SPELL_MANA_DETONATION = 60182,
|
||||
};
|
||||
|
||||
enum AzureRaiderSpells
|
||||
@@ -114,7 +115,7 @@ enum TrashDoorSpell
|
||||
enum Spells
|
||||
{
|
||||
SPELL_PORTAL_CHANNEL = 58012,
|
||||
SPELL_CRYSTAL_ACTIVATION = 57804,
|
||||
SPELL_CRYSTAL_ACTIVATION = 57804, // visual effect
|
||||
SPELL_ARCANE_SPHERE_PASSIVE = 44263
|
||||
};
|
||||
|
||||
@@ -242,9 +243,21 @@ const float SaboteurFinalPos6[5][3] =
|
||||
{1931.063354f, 848.468445f, 47.190434f}
|
||||
};
|
||||
|
||||
const Position MovePosition = {1806.955566f, 803.851807f, 44.363323f, 0.0f};
|
||||
const Position playerTeleportPosition = {1830.531006f, 803.939758f, 44.340508f, 6.281611f};
|
||||
const Position sinclariOutsidePosition = {1817.315674f, 804.060608f, 44.363998f, 0.0f};
|
||||
const Position PortalLocation[] =
|
||||
{
|
||||
{ 1877.51f, 850.104f, 44.6599f, 4.7822f }, // WP 1
|
||||
{ 1936.07f, 803.198f, 53.3749f, 3.12414f }, // WP 3
|
||||
{ 1890.64f, 753.471f, 48.7224f, 1.71042f }, // WP 5
|
||||
};
|
||||
|
||||
#define MAX_PRE_EVENT_PORTAL 3
|
||||
|
||||
ObjectGuid preEventPortalGUID[MAX_PRE_EVENT_PORTAL] = { ObjectGuid::Empty };
|
||||
|
||||
const Position MovePosition = { 1806.955566f, 803.851807f, 44.363323f, 0.0f };
|
||||
const Position playerTeleportPosition = { 1830.531006f, 803.939758f, 44.340508f, 6.281611f };
|
||||
const Position sinclariOutsidePosition = { 1820.429810f, 804.066040f, 44.363998f, 0.0f };
|
||||
const Position sinclariCrystalPosition = { 1828.868286f, 798.468811f, 44.363998f, 3.890467f };
|
||||
|
||||
class npc_sinclari_vh : public CreatureScript
|
||||
{
|
||||
@@ -258,7 +271,7 @@ public:
|
||||
{
|
||||
case GOSSIP_ACTION_INFO_DEF+1:
|
||||
player->CLOSE_GOSSIP_MENU();
|
||||
ENSURE_AI(npc_sinclari_vh::npc_sinclariAI, (creature->AI()))->uiPhase = 1;
|
||||
ENSURE_AI(npc_sinclari_vh::npc_sinclariAI, creature->AI())->uiPhase = 1;
|
||||
if (InstanceScript* instance = creature->GetInstanceScript())
|
||||
instance->SetData(DATA_MAIN_EVENT_PHASE, SPECIAL);
|
||||
break;
|
||||
@@ -296,17 +309,12 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_sinclariAI>(creature);
|
||||
}
|
||||
|
||||
struct npc_sinclariAI : public ScriptedAI
|
||||
{
|
||||
npc_sinclariAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
@@ -325,6 +333,9 @@ public:
|
||||
Initialize();
|
||||
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
for (uint8 i = 0; i < MAX_PRE_EVENT_PORTAL; i++)
|
||||
if (TempSummon* summon = me->SummonCreature(NPC_TELEPORTATION_PORTAL, PortalLocation[i], TEMPSUMMON_MANUAL_DESPAWN))
|
||||
preEventPortalGUID[i] = summon->GetGUID();
|
||||
|
||||
std::list<Creature*> GuardList;
|
||||
me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f);
|
||||
@@ -345,8 +356,6 @@ public:
|
||||
|
||||
void UpdateAI(uint32 uiDiff) override
|
||||
{
|
||||
ScriptedAI::UpdateAI(uiDiff);
|
||||
|
||||
if (uiPhase)
|
||||
{
|
||||
if (uiTimer <= uiDiff)
|
||||
@@ -354,25 +363,17 @@ public:
|
||||
switch (uiPhase)
|
||||
{
|
||||
case 1:
|
||||
Talk(SAY_SINCLARI_1);
|
||||
uiTimer = 4000;
|
||||
uiPhase = 2;
|
||||
me->SetWalk(true);
|
||||
me->GetMotionMaster()->MovePoint(0, sinclariCrystalPosition);
|
||||
uiTimer = 1000;
|
||||
uiPhase = 6;
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
std::list<Creature*> GuardList;
|
||||
me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f);
|
||||
if (!GuardList.empty())
|
||||
for (std::list<Creature*>::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr)
|
||||
{
|
||||
if (Creature* pGuard = *itr)
|
||||
{
|
||||
pGuard->SetWalk(false);
|
||||
pGuard->GetMotionMaster()->MovePoint(0, MovePosition);
|
||||
}
|
||||
}
|
||||
uiTimer = 6000;
|
||||
uiPhase = 3;
|
||||
me->SetFacingTo(me->GetOrientation() - 3.14f);
|
||||
Talk(SAY_SINCLARI_1);
|
||||
uiTimer = 1500;
|
||||
uiPhase = 7;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
@@ -385,7 +386,6 @@ public:
|
||||
if (Creature* pGuard = *itr)
|
||||
{
|
||||
pGuard->SetVisible(false);
|
||||
pGuard->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
}
|
||||
uiTimer = 2000;
|
||||
@@ -398,11 +398,58 @@ public:
|
||||
uiPhase = 5;
|
||||
break;
|
||||
case 5:
|
||||
instance->SetData(DATA_MAIN_EVENT_PHASE, IN_PROGRESS);
|
||||
me->SetFacingTo(0.006673f);
|
||||
me->Say(SAY_EVENT_LOCK, LANG_UNIVERSAL, me); // need to change to db say
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
uiTimer = 3000;
|
||||
uiPhase = 8;
|
||||
break;
|
||||
case 6:
|
||||
me->GetMotionMaster()->MovementExpired();
|
||||
me->HandleEmoteCommand(EMOTE_STATE_USE_STANDING);
|
||||
uiTimer = 2000;
|
||||
uiPhase = 2;
|
||||
break;
|
||||
case 7:
|
||||
{
|
||||
std::list<Creature*> creatures;
|
||||
GetCreatureListWithEntryInGrid(creatures, me, NPC_TELEPORTATION_PORTAL, 200.0f);
|
||||
GetCreatureListWithEntryInGrid(creatures, me, NPC_AZURE_BINDER_1, 200.0f);
|
||||
GetCreatureListWithEntryInGrid(creatures, me, NPC_AZURE_MAGE_SLAYER_1, 200.0f);
|
||||
GetCreatureListWithEntryInGrid(creatures, me, NPC_AZURE_INVADER_1, 200.0f);
|
||||
DoCast(SPELL_CRYSTAL_ACTIVATION);
|
||||
if (!creatures.empty())
|
||||
{
|
||||
for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr)
|
||||
(*itr)->DisappearAndDie();
|
||||
}
|
||||
uiTimer = 500;
|
||||
uiPhase = 9;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
instance->SetData(DATA_MAIN_EVENT_PHASE, IN_PROGRESS);
|
||||
uiTimer = 0;
|
||||
uiPhase = 0;
|
||||
break;
|
||||
case 9:
|
||||
{
|
||||
std::list<Creature*> GuardList;
|
||||
me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f);
|
||||
if (!GuardList.empty())
|
||||
for (std::list<Creature*>::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr)
|
||||
{
|
||||
if (Creature* pGuard = *itr)
|
||||
{
|
||||
pGuard->SetReactState(REACT_PASSIVE);
|
||||
pGuard->SetWalk(false);
|
||||
pGuard->GetMotionMaster()->MovePoint(0, MovePosition);
|
||||
}
|
||||
}
|
||||
uiTimer = 4000;
|
||||
uiPhase = 3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else uiTimer -= uiDiff;
|
||||
@@ -415,6 +462,10 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_sinclariAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_azure_saboteur : public CreatureScript
|
||||
@@ -422,14 +473,9 @@ class npc_azure_saboteur : public CreatureScript
|
||||
public:
|
||||
npc_azure_saboteur() : CreatureScript("npc_azure_saboteur") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_azure_saboteurAI>(creature);
|
||||
}
|
||||
|
||||
struct npc_azure_saboteurAI : public npc_escortAI
|
||||
{
|
||||
npc_azure_saboteurAI(Creature* creature):npc_escortAI(creature)
|
||||
npc_azure_saboteurAI(Creature* creature) : npc_escortAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
bHasGotMovingPoints = false;
|
||||
@@ -532,13 +578,16 @@ public:
|
||||
{
|
||||
me->CastSpell(me, SABOTEUR_SHIELD_DISRUPTION, false);
|
||||
me->DisappearAndDie();
|
||||
Creature* pSaboPort = ObjectAccessor::GetCreature((*me), instance->GetGuidData(DATA_SABOTEUR_PORTAL));
|
||||
if (pSaboPort)
|
||||
if (Creature* pSaboPort = ObjectAccessor::GetCreature((*me), instance->GetGuidData(DATA_SABOTEUR_PORTAL)))
|
||||
pSaboPort->DisappearAndDie();
|
||||
instance->SetData(DATA_START_BOSS_ENCOUNTER, 1);
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_azure_saboteurAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_teleportation_portal_vh : public CreatureScript
|
||||
@@ -546,11 +595,6 @@ class npc_teleportation_portal_vh : public CreatureScript
|
||||
public:
|
||||
npc_teleportation_portal_vh() : CreatureScript("npc_teleportation_portal_vh") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_teleportation_portalAI>(creature);
|
||||
}
|
||||
|
||||
struct npc_teleportation_portalAI : public ScriptedAI
|
||||
{
|
||||
npc_teleportation_portalAI(Creature* creature) : ScriptedAI(creature), listOfMobs(me)
|
||||
@@ -558,6 +602,9 @@ public:
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
uiTypeOfMobsPortal = urand(0, 1); // 0 - elite mobs 1 - portal guardian or portal keeper with regular mobs
|
||||
|
||||
if (instance->GetData(DATA_MAIN_EVENT_PHASE) == NOT_STARTED)
|
||||
uiTypeOfMobsPortal = 2;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
@@ -583,13 +630,15 @@ public:
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (instance->GetData(DATA_REMOVE_NPC) == 1)
|
||||
if (instance->GetData(DATA_MAIN_EVENT_PHASE) == IN_PROGRESS)
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
instance->SetData(DATA_REMOVE_NPC, 0);
|
||||
if (instance->GetData(DATA_REMOVE_NPC) == 1)
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
instance->SetData(DATA_REMOVE_NPC, 0);
|
||||
}
|
||||
}
|
||||
|
||||
uint8 uiWaveCount = instance->GetData(DATA_WAVE_COUNT);
|
||||
@@ -608,7 +657,7 @@ public:
|
||||
uint8 k = uiWaveCount < 12 ? 2 : 3;
|
||||
for (uint8 i = 0; i < k; ++i)
|
||||
{
|
||||
uint32 entry = RAND(CREATURE_AZURE_CAPTAIN, CREATURE_AZURE_RAIDER, CREATURE_AZURE_STALKER, CREATURE_AZURE_SORCEROR);
|
||||
uint32 entry = RAND(NPC_AZURE_CAPTAIN, NPC_AZURE_RAIDER, NPC_AZURE_STALKER, NPC_AZURE_SORCEROR);
|
||||
DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN);
|
||||
}
|
||||
me->SetVisible(false);
|
||||
@@ -633,14 +682,14 @@ public:
|
||||
uint8 k = instance->GetData(DATA_WAVE_COUNT) < 12 ? 3 : 4;
|
||||
for (uint8 i = 0; i < k; ++i)
|
||||
{
|
||||
uint32 entry = RAND(CREATURE_AZURE_INVADER_1, CREATURE_AZURE_INVADER_2, CREATURE_AZURE_SPELLBREAKER_1, CREATURE_AZURE_SPELLBREAKER_2, CREATURE_AZURE_MAGE_SLAYER_1, CREATURE_AZURE_MAGE_SLAYER_2, CREATURE_AZURE_BINDER_1, CREATURE_AZURE_BINDER_2);
|
||||
uint32 entry = RAND(NPC_AZURE_INVADER_1, NPC_AZURE_INVADER_2, NPC_AZURE_SPELLBREAKER_1, NPC_AZURE_SPELLBREAKER_2, NPC_AZURE_MAGE_SLAYER_1, NPC_AZURE_MAGE_SLAYER_2, NPC_AZURE_BINDER_1, NPC_AZURE_BINDER_2);
|
||||
DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bPortalGuardianOrKeeperOrEliteSpawn = true;
|
||||
uint32 entry = RAND(CREATURE_PORTAL_GUARDIAN, CREATURE_PORTAL_KEEPER);
|
||||
uint32 entry = RAND(NPC_PORTAL_GUARDIAN, NPC_PORTAL_KEEPER);
|
||||
if (Creature* pPortalKeeper = DoSummon(entry, me, 2.0f, 0, TEMPSUMMON_DEAD_DESPAWN))
|
||||
me->CastSpell(pPortalKeeper, SPELL_PORTAL_CHANNEL, false);
|
||||
}
|
||||
@@ -653,37 +702,71 @@ public:
|
||||
me->RemoveCorpse();
|
||||
}
|
||||
break;
|
||||
case 2: // Pre-event
|
||||
if (uiSpawnTimer <= diff)
|
||||
{
|
||||
uint32 entry = RAND(NPC_AZURE_INVADER_1, NPC_AZURE_MAGE_SLAYER_1, NPC_AZURE_BINDER_1);
|
||||
DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN);
|
||||
uiSpawnTimer = SPAWN_TIME;
|
||||
} else uiSpawnTimer -= diff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SetData(DATA_WAVE_COUNT, instance->GetData(DATA_WAVE_COUNT)+1);
|
||||
if (instance->GetData(DATA_MAIN_EVENT_PHASE) == IN_PROGRESS)
|
||||
instance->SetData(DATA_WAVE_COUNT, instance->GetData(DATA_WAVE_COUNT) + 1);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summoned) override
|
||||
{
|
||||
listOfMobs.Summon(summoned);
|
||||
instance->SetGuidData(DATA_ADD_TRASH_MOB, summoned->GetGUID());
|
||||
if (instance->GetData(DATA_MAIN_EVENT_PHASE) == IN_PROGRESS)
|
||||
{
|
||||
listOfMobs.Summon(summoned);
|
||||
instance->SetGuidData(DATA_ADD_TRASH_MOB, summoned->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summoned, Unit* /*killer*/) override
|
||||
{
|
||||
listOfMobs.Despawn(summoned);
|
||||
instance->SetGuidData(DATA_DEL_TRASH_MOB, summoned->GetGUID());
|
||||
if (instance->GetData(DATA_MAIN_EVENT_PHASE) == IN_PROGRESS)
|
||||
{
|
||||
listOfMobs.Despawn(summoned);
|
||||
instance->SetGuidData(DATA_DEL_TRASH_MOB, summoned->GetGUID());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_teleportation_portalAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
struct violet_hold_trashAI : public npc_escortAI
|
||||
{
|
||||
violet_hold_trashAI(Creature* creature):npc_escortAI(creature)
|
||||
violet_hold_trashAI(Creature* creature) : npc_escortAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
bHasGotMovingPoints = false;
|
||||
portalLocationID = instance->GetData(DATA_PORTAL_LOCATION);
|
||||
secondPortalRouteID = 0;
|
||||
|
||||
|
||||
if (instance->GetData(DATA_MAIN_EVENT_PHASE) == NOT_STARTED)
|
||||
{
|
||||
if (Creature* portal = me->FindNearestCreature(NPC_TELEPORTATION_PORTAL, 10.0f))
|
||||
{
|
||||
ObjectGuid portalGUID = portal->GetGUID();
|
||||
for (uint8 i = 0; i < MAX_PRE_EVENT_PORTAL; i++)
|
||||
if (portalGUID == preEventPortalGUID[i])
|
||||
portalLocationID = i * 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
portalLocationID = instance->GetData(DATA_PORTAL_LOCATION);
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -698,7 +781,7 @@ struct violet_hold_trashAI : public npc_escortAI
|
||||
{
|
||||
case 0:
|
||||
if (waypointId == 5)
|
||||
CreatureStartAttackDoor();
|
||||
CreatureStartAttackDoor();
|
||||
break;
|
||||
case 1:
|
||||
if ((waypointId == 8 && secondPortalRouteID == 0) || (waypointId == 7 && secondPortalRouteID == 1))
|
||||
@@ -706,7 +789,7 @@ struct violet_hold_trashAI : public npc_escortAI
|
||||
break;
|
||||
case 2:
|
||||
if (waypointId == 7)
|
||||
CreatureStartAttackDoor();
|
||||
CreatureStartAttackDoor();
|
||||
break;
|
||||
case 3:
|
||||
if (waypointId == 8)
|
||||
@@ -723,7 +806,7 @@ struct violet_hold_trashAI : public npc_escortAI
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32) override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (instance->GetData(DATA_MAIN_EVENT_PHASE) != IN_PROGRESS)
|
||||
me->CastStop();
|
||||
@@ -778,6 +861,8 @@ struct violet_hold_trashAI : public npc_escortAI
|
||||
SetDespawnAtEnd(false);
|
||||
Start(true, true);
|
||||
}
|
||||
|
||||
npc_escortAI::UpdateAI(diff);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -791,7 +876,6 @@ struct violet_hold_trashAI : public npc_escortAI
|
||||
DoCast(SPELL_DESTROY_DOOR_SEAL);
|
||||
instance->SetData(DATA_NPC_PRESENCE_AT_DOOR_ADD, 1);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class npc_azure_invader : public CreatureScript
|
||||
@@ -799,11 +883,6 @@ class npc_azure_invader : public CreatureScript
|
||||
public:
|
||||
npc_azure_invader() : CreatureScript("npc_azure_invader") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_azure_invaderAI>(creature);
|
||||
}
|
||||
|
||||
struct npc_azure_invaderAI : public violet_hold_trashAI
|
||||
{
|
||||
npc_azure_invaderAI(Creature* creature) : violet_hold_trashAI(creature)
|
||||
@@ -833,12 +912,11 @@ public:
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
violet_hold_trashAI::UpdateAI(diff);
|
||||
npc_escortAI::UpdateAI(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (me->GetEntry() == CREATURE_AZURE_INVADER_1)
|
||||
if (me->GetEntry() == NPC_AZURE_INVADER_1)
|
||||
{
|
||||
if (uiCleaveTimer <= diff)
|
||||
{
|
||||
@@ -848,14 +926,13 @@ public:
|
||||
|
||||
if (uiImpaleTimer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
|
||||
if (target)
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_IMPALE);
|
||||
uiImpaleTimer = 4000;
|
||||
} else uiImpaleTimer -= diff;
|
||||
}
|
||||
|
||||
if (me->GetEntry() == CREATURE_AZURE_INVADER_2)
|
||||
if (me->GetEntry() == NPC_AZURE_INVADER_2)
|
||||
{
|
||||
if (uiBrutalStrikeTimer <= diff)
|
||||
{
|
||||
@@ -876,6 +953,10 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_azure_invaderAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_azure_binder : public CreatureScript
|
||||
@@ -883,11 +964,6 @@ class npc_azure_binder : public CreatureScript
|
||||
public:
|
||||
npc_azure_binder() : CreatureScript("npc_azure_binder") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_azure_binderAI>(creature);
|
||||
}
|
||||
|
||||
struct npc_azure_binderAI : public violet_hold_trashAI
|
||||
{
|
||||
npc_azure_binderAI(Creature* creature) : violet_hold_trashAI(creature)
|
||||
@@ -917,12 +993,11 @@ public:
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
violet_hold_trashAI::UpdateAI(diff);
|
||||
npc_escortAI::UpdateAI(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (me->GetEntry() == CREATURE_AZURE_BINDER_1)
|
||||
if (me->GetEntry() == NPC_AZURE_BINDER_1)
|
||||
{
|
||||
if (uiArcaneExplosionTimer <= diff)
|
||||
{
|
||||
@@ -930,16 +1005,15 @@ public:
|
||||
uiArcaneExplosionTimer = 5000;
|
||||
} else uiArcaneExplosionTimer -= diff;
|
||||
|
||||
if (uiArcainBarrageTimer <= diff)
|
||||
if (uiArcainBarrageTimer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
|
||||
if (target)
|
||||
DoCast(target, SPELL_ARCANE_BARRAGE);
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_ARCANE_BARRAGE);
|
||||
uiArcainBarrageTimer = 6000;
|
||||
} else uiArcainBarrageTimer -= diff;
|
||||
}
|
||||
|
||||
if (me->GetEntry() == CREATURE_AZURE_BINDER_2)
|
||||
if (me->GetEntry() == NPC_AZURE_BINDER_2)
|
||||
{
|
||||
if (uiFrostNovaTimer <= diff)
|
||||
{
|
||||
@@ -949,8 +1023,7 @@ public:
|
||||
|
||||
if (uiFrostboltTimer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
|
||||
if (target)
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_FROSTBOLT);
|
||||
uiFrostboltTimer = 6000;
|
||||
} else uiFrostboltTimer -= diff;
|
||||
@@ -960,6 +1033,10 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_azure_binderAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_azure_mage_slayer : public CreatureScript
|
||||
@@ -967,11 +1044,6 @@ class npc_azure_mage_slayer : public CreatureScript
|
||||
public:
|
||||
npc_azure_mage_slayer() : CreatureScript("npc_azure_mage_slayer") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_azure_mage_slayerAI>(creature);
|
||||
}
|
||||
|
||||
struct npc_azure_mage_slayerAI : public violet_hold_trashAI
|
||||
{
|
||||
npc_azure_mage_slayerAI(Creature* creature) : violet_hold_trashAI(creature)
|
||||
@@ -997,12 +1069,11 @@ public:
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
violet_hold_trashAI::UpdateAI(diff);
|
||||
npc_escortAI::UpdateAI(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (me->GetEntry() == CREATURE_AZURE_MAGE_SLAYER_1)
|
||||
if (me->GetEntry() == NPC_AZURE_MAGE_SLAYER_1)
|
||||
{
|
||||
if (uiArcaneEmpowermentTimer <= diff)
|
||||
{
|
||||
@@ -1011,12 +1082,11 @@ public:
|
||||
} else uiArcaneEmpowermentTimer -= diff;
|
||||
}
|
||||
|
||||
if (me->GetEntry() == CREATURE_AZURE_MAGE_SLAYER_2)
|
||||
if (me->GetEntry() == NPC_AZURE_MAGE_SLAYER_2)
|
||||
{
|
||||
if (uiSpellLockTimer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
|
||||
if (target)
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_SPELL_LOCK);
|
||||
uiSpellLockTimer = 9000;
|
||||
} else uiSpellLockTimer -= diff;
|
||||
@@ -1026,6 +1096,10 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_azure_mage_slayerAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_azure_raider : public CreatureScript
|
||||
@@ -1033,11 +1107,6 @@ class npc_azure_raider : public CreatureScript
|
||||
public:
|
||||
npc_azure_raider() : CreatureScript("npc_azure_raider") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_azure_raiderAI>(creature);
|
||||
}
|
||||
|
||||
struct npc_azure_raiderAI : public violet_hold_trashAI
|
||||
{
|
||||
npc_azure_raiderAI(Creature* creature) : violet_hold_trashAI(creature)
|
||||
@@ -1063,7 +1132,6 @@ public:
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
violet_hold_trashAI::UpdateAI(diff);
|
||||
npc_escortAI::UpdateAI(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
@@ -1084,6 +1152,10 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_azure_raiderAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_azure_stalker : public CreatureScript
|
||||
@@ -1114,7 +1186,6 @@ public:
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
violet_hold_trashAI::UpdateAI(diff);
|
||||
npc_escortAI::UpdateAI(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
@@ -1123,8 +1194,7 @@ public:
|
||||
{
|
||||
if (_tacticalBlinkTimer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true);
|
||||
if (target)
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true))
|
||||
DoCast(target, SPELL_TACTICAL_BLINK);
|
||||
_tacticalBlinkTimer = 6000;
|
||||
_tacticalBlinkCast = true;
|
||||
@@ -1135,8 +1205,8 @@ public:
|
||||
{
|
||||
if (_backstabTimer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 10, true);
|
||||
DoCast(target, SPELL_BACKSTAB);
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 10, true))
|
||||
DoCast(target, SPELL_BACKSTAB);
|
||||
_tacticalBlinkCast = false;
|
||||
_backstabTimer =1300;
|
||||
} else _backstabTimer -= diff;
|
||||
@@ -1191,43 +1261,39 @@ public:
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
violet_hold_trashAI::UpdateAI(diff);
|
||||
npc_escortAI::UpdateAI(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (me->GetEntry() == CREATURE_AZURE_SPELLBREAKER_1)
|
||||
if (me->GetEntry() == NPC_AZURE_SPELLBREAKER_1)
|
||||
{
|
||||
if (uiArcaneBlastTimer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
|
||||
if (target)
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_ARCANE_BLAST);
|
||||
uiArcaneBlastTimer = 6000;
|
||||
} else uiArcaneBlastTimer -= diff;
|
||||
|
||||
if (uiSlowTimer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
|
||||
if (target)
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_SLOW);
|
||||
uiSlowTimer = 5000;
|
||||
} else uiSlowTimer -= diff;
|
||||
}
|
||||
|
||||
if (me->GetEntry() == CREATURE_AZURE_SPELLBREAKER_2)
|
||||
if (me->GetEntry() == NPC_AZURE_SPELLBREAKER_2)
|
||||
{
|
||||
if (uiChainsOfIceTimer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
|
||||
if (target)
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_CHAINS_OF_ICE);
|
||||
uiChainsOfIceTimer = 7000;
|
||||
} else uiChainsOfIceTimer -= diff;
|
||||
|
||||
if (uiConeOfColdTimer <= diff)
|
||||
{
|
||||
DoCast(SPELL_CONE_OF_COLD);
|
||||
DoCast(SPELL_CONE_OF_COLD);
|
||||
uiConeOfColdTimer = 5000;
|
||||
} else uiConeOfColdTimer -= diff;
|
||||
}
|
||||
@@ -1247,11 +1313,6 @@ class npc_azure_captain : public CreatureScript
|
||||
public:
|
||||
npc_azure_captain() : CreatureScript("npc_azure_captain") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_azure_captainAI>(creature);
|
||||
}
|
||||
|
||||
struct npc_azure_captainAI : public violet_hold_trashAI
|
||||
{
|
||||
npc_azure_captainAI(Creature* creature) : violet_hold_trashAI(creature)
|
||||
@@ -1277,7 +1338,6 @@ public:
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
violet_hold_trashAI::UpdateAI(diff);
|
||||
npc_escortAI::UpdateAI(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
@@ -1298,6 +1358,10 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_azure_captainAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_azure_sorceror : public CreatureScript
|
||||
@@ -1305,11 +1369,6 @@ class npc_azure_sorceror : public CreatureScript
|
||||
public:
|
||||
npc_azure_sorceror() : CreatureScript("npc_azure_sorceror") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_azure_sorcerorAI>(creature);
|
||||
}
|
||||
|
||||
struct npc_azure_sorcerorAI : public violet_hold_trashAI
|
||||
{
|
||||
npc_azure_sorcerorAI(Creature* creature) : violet_hold_trashAI(creature)
|
||||
@@ -1337,15 +1396,13 @@ public:
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
violet_hold_trashAI::UpdateAI(diff);
|
||||
npc_escortAI::UpdateAI(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (uiArcaneStreamTimer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
|
||||
if (target)
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_ARCANE_STREAM);
|
||||
uiArcaneStreamTimer = urand(0, 5000)+5000;
|
||||
uiArcaneStreamTimerStartingValueHolder = uiArcaneStreamTimer;
|
||||
@@ -1360,8 +1417,12 @@ public:
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_azure_sorcerorAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_violet_hold_arcane_sphere : public CreatureScript
|
||||
{
|
||||
@@ -1419,6 +1480,33 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class spell_crystal_activation : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_crystal_activation() : SpellScriptLoader("spell_crystal_activation") { }
|
||||
|
||||
class spell_crystal_activation_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_crystal_activation_SpellScript);
|
||||
|
||||
void HandleSendEvent(SpellEffIndex effIndex)
|
||||
{
|
||||
if (GetHitUnit()->GetEntry() == NPC_VIOLET_HOLD_GUARD)
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_crystal_activation_SpellScript::HandleSendEvent, EFFECT_0, SPELL_EFFECT_SEND_EVENT);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_crystal_activation_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_violet_hold()
|
||||
{
|
||||
new npc_sinclari_vh();
|
||||
@@ -1434,4 +1522,5 @@ void AddSC_violet_hold()
|
||||
new npc_azure_saboteur();
|
||||
new npc_violet_hold_arcane_sphere();
|
||||
new go_activation_crystal();
|
||||
new spell_crystal_activation();
|
||||
}
|
||||
|
||||
@@ -18,13 +18,18 @@
|
||||
#ifndef DEF_VIOLET_HOLD_H
|
||||
#define DEF_VIOLET_HOLD_H
|
||||
|
||||
#define DataHeader "VIO"
|
||||
#define DataHeader "VH"
|
||||
|
||||
uint32 const EncounterCount = 3;
|
||||
|
||||
enum Data
|
||||
{
|
||||
// Main encounters
|
||||
DATA_1ST_BOSS_EVENT,
|
||||
DATA_2ND_BOSS_EVENT,
|
||||
DATA_CYANIGOSA_EVENT,
|
||||
DATA_CYANIGOSA,
|
||||
|
||||
// Misc
|
||||
DATA_WAVE_COUNT,
|
||||
DATA_REMOVE_NPC,
|
||||
DATA_PORTAL_LOCATION,
|
||||
@@ -38,10 +43,8 @@ enum Data
|
||||
DATA_ACTIVATE_CRYSTAL,
|
||||
DATA_MAIN_EVENT_PHASE,
|
||||
DATA_DEFENSELESS,
|
||||
};
|
||||
|
||||
enum Data64
|
||||
{
|
||||
// Bosses
|
||||
DATA_MORAGG,
|
||||
DATA_EREKEM,
|
||||
DATA_EREKEM_GUARD_1,
|
||||
@@ -50,7 +53,8 @@ enum Data64
|
||||
DATA_LAVANTHOR,
|
||||
DATA_XEVOZZ,
|
||||
DATA_ZURAMAT,
|
||||
DATA_CYANIGOSA,
|
||||
|
||||
// Cells
|
||||
DATA_MORAGG_CELL,
|
||||
DATA_EREKEM_CELL,
|
||||
DATA_EREKEM_LEFT_GUARD_CELL,
|
||||
@@ -59,6 +63,8 @@ enum Data64
|
||||
DATA_LAVANTHOR_CELL,
|
||||
DATA_XEVOZZ_CELL,
|
||||
DATA_ZURAMAT_CELL,
|
||||
|
||||
// Misc
|
||||
DATA_MAIN_DOOR,
|
||||
DATA_SINCLARI,
|
||||
DATA_TELEPORTATION_PORTAL,
|
||||
@@ -81,33 +87,50 @@ enum Bosses
|
||||
|
||||
enum CreaturesIds
|
||||
{
|
||||
CREATURE_TELEPORTATION_PORTAL = 31011,
|
||||
CREATURE_PORTAL_GUARDIAN = 30660,
|
||||
CREATURE_PORTAL_KEEPER = 30695,
|
||||
CREATURE_XEVOZZ = 29266,
|
||||
CREATURE_LAVANTHOR = 29312,
|
||||
CREATURE_ICHORON = 29313,
|
||||
CREATURE_ZURAMAT = 29314,
|
||||
CREATURE_EREKEM = 29315,
|
||||
CREATURE_EREKEM_GUARD = 29395,
|
||||
CREATURE_MORAGG = 29316,
|
||||
CREATURE_CYANIGOSA = 31134,
|
||||
CREATURE_SINCLARI = 30658,
|
||||
CREATURE_SABOTEOUR = 31079,
|
||||
NPC_VIOLET_HOLD_GUARD = 30659,
|
||||
NPC_DEFENSE_SYSTEM = 30837
|
||||
NPC_TELEPORTATION_PORTAL = 31011,
|
||||
NPC_PORTAL_GUARDIAN = 30660,
|
||||
NPC_PORTAL_KEEPER = 30695,
|
||||
NPC_XEVOZZ = 29266,
|
||||
NPC_LAVANTHOR = 29312,
|
||||
NPC_ICHORON = 29313,
|
||||
NPC_ZURAMAT = 29314,
|
||||
NPC_EREKEM = 29315,
|
||||
NPC_EREKEM_GUARD = 29395,
|
||||
NPC_MORAGG = 29316,
|
||||
NPC_CYANIGOSA = 31134,
|
||||
NPC_SINCLARI = 30658,
|
||||
NPC_SABOTEOUR = 31079,
|
||||
NPC_VIOLET_HOLD_GUARD = 30659,
|
||||
NPC_DEFENSE_SYSTEM = 30837,
|
||||
NPC_VOID_SENTRY = 29364,
|
||||
NPC_VOID_SENTRY_BALL = 29365
|
||||
};
|
||||
|
||||
enum GameObjectIds
|
||||
{
|
||||
GO_MAIN_DOOR = 191723,
|
||||
GO_XEVOZZ_DOOR = 191556,
|
||||
GO_LAVANTHOR_DOOR = 191566,
|
||||
GO_ICHORON_DOOR = 191722,
|
||||
GO_ZURAMAT_DOOR = 191565,
|
||||
GO_EREKEM_DOOR = 191564,
|
||||
GO_EREKEM_GUARD_1_DOOR = 191563,
|
||||
GO_EREKEM_GUARD_2_DOOR = 191562,
|
||||
GO_MORAGG_DOOR = 191606,
|
||||
GO_INTRO_ACTIVATION_CRYSTAL = 193615,
|
||||
GO_ACTIVATION_CRYSTAL = 193611
|
||||
};
|
||||
|
||||
enum WorldStateIds
|
||||
{
|
||||
WORLD_STATE_VH = 3816,
|
||||
WORLD_STATE_VH_PRISON_STATE = 3815,
|
||||
WORLD_STATE_VH_WAVE_COUNT = 3810,
|
||||
WORLD_STATE_VH = 3816,
|
||||
WORLD_STATE_VH_PRISON_STATE = 3815,
|
||||
WORLD_STATE_VH_WAVE_COUNT = 3810,
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_ACTIVATE_CRYSTAL = 20001
|
||||
EVENT_ACTIVATE_CRYSTAL = 20001
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user