refactor(Scripts/VioletHold): Modernize Violet Hold dungeon scripts (#25187)
Co-authored-by: joschiwald <joschiwald@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1810,12 +1810,13 @@ void Map::RemoveAllObjectsInRemoveList()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Map::GetPlayersCountExceptGMs() const
|
uint32 Map::GetPlayersCountExceptGMs(bool aliveOnly /*= false*/) const
|
||||||
{
|
{
|
||||||
uint32 count = 0;
|
uint32 count = 0;
|
||||||
for (MapRefMgr::const_iterator itr = m_mapRefMgr.begin(); itr != m_mapRefMgr.end(); ++itr)
|
for (auto const& ref : m_mapRefMgr)
|
||||||
if (!itr->GetSource()->IsGameMaster())
|
if (Player* player = ref.GetSource())
|
||||||
++count;
|
if (!player->IsGameMaster() && (!aliveOnly || (player->IsAlive() && !player->HasSpiritOfRedemptionAura())))
|
||||||
|
++count;
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -318,7 +318,8 @@ public:
|
|||||||
void markCell(uint32 pCellId) { marked_cells.set(pCellId); }
|
void markCell(uint32 pCellId) { marked_cells.set(pCellId); }
|
||||||
|
|
||||||
[[nodiscard]] bool HavePlayers() const { return !m_mapRefMgr.IsEmpty(); }
|
[[nodiscard]] bool HavePlayers() const { return !m_mapRefMgr.IsEmpty(); }
|
||||||
[[nodiscard]] uint32 GetPlayersCountExceptGMs() const;
|
// When aliveOnly is true, counts only players that are alive and not in Spirit of Redemption form.
|
||||||
|
[[nodiscard]] uint32 GetPlayersCountExceptGMs(bool aliveOnly = false) const;
|
||||||
|
|
||||||
void SendToPlayers(WorldPacket const* data) const;
|
void SendToPlayers(WorldPacket const* data) const;
|
||||||
|
|
||||||
|
|||||||
@@ -50,141 +50,95 @@ enum eEvents
|
|||||||
EVENT_UNROOT,
|
EVENT_UNROOT,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_cyanigosa : public CreatureScript
|
struct boss_cyanigosa : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_cyanigosa(Creature* c) : BossAI(c, DATA_CYANIGOSA) { }
|
||||||
boss_cyanigosa() : CreatureScript("boss_cyanigosa") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* pCreature) const override
|
void JustEngagedWith(Unit* who) override
|
||||||
{
|
{
|
||||||
return GetVioletHoldAI<boss_cyanigosaAI>(pCreature);
|
BossAI::JustEngagedWith(who);
|
||||||
|
Talk(SAY_AGGRO);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_ARCANE_VACUUM, 30s);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_BLIZZARD, 5s, 10s);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_TAIL_SWEEP, 15s, 20s);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_UNCONTROLLABLE_ENERGY, 5s, 8s);
|
||||||
|
if (IsHeroic())
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_MANA_DESTRUCTION, 20s);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct boss_cyanigosaAI : public ScriptedAI
|
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
|
||||||
{
|
{
|
||||||
boss_cyanigosaAI(Creature* c) : ScriptedAI(c)
|
if (!target || !spell)
|
||||||
|
return;
|
||||||
|
if (spell->Id == SPELL_ARCANE_VACUUM)
|
||||||
|
target->NearTeleportTo(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10.0f, target->GetOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExecuteEvent(uint32 eventId) override
|
||||||
|
{
|
||||||
|
switch (eventId)
|
||||||
{
|
{
|
||||||
pInstance = c->GetInstanceScript();
|
case EVENT_SPELL_ARCANE_VACUUM:
|
||||||
|
DoCastAOE(SPELL_ARCANE_VACUUM);
|
||||||
|
DoResetThreatList();
|
||||||
|
me->SetControlled(true, UNIT_STATE_ROOT);
|
||||||
|
me->setAttackTimer(BASE_ATTACK, 3000);
|
||||||
|
events.Repeat(30s);
|
||||||
|
events.ScheduleEvent(EVENT_UNROOT, 3s);
|
||||||
|
break;
|
||||||
|
case EVENT_UNROOT:
|
||||||
|
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||||
|
break;
|
||||||
|
case EVENT_SPELL_BLIZZARD:
|
||||||
|
DoCastRandomTarget(SPELL_BLIZZARD, 0, 45.0f);
|
||||||
|
events.Repeat(15s);
|
||||||
|
break;
|
||||||
|
case EVENT_SPELL_MANA_DESTRUCTION:
|
||||||
|
DoCastRandomTarget(SPELL_MANA_DESTRUCTION, 0, 50.0f);
|
||||||
|
events.Repeat(20s);
|
||||||
|
break;
|
||||||
|
case EVENT_SPELL_TAIL_SWEEP:
|
||||||
|
DoCastVictim(SPELL_TAIL_SWEEP);
|
||||||
|
events.Repeat(15s, 20s);
|
||||||
|
break;
|
||||||
|
case EVENT_SPELL_UNCONTROLLABLE_ENERGY:
|
||||||
|
DoCastVictim(SPELL_UNCONTROLLABLE_ENERGY);
|
||||||
|
events.Repeat(20s, 25s);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InstanceScript* pInstance;
|
void JustDied(Unit* killer) override
|
||||||
EventMap events;
|
{
|
||||||
|
Talk(SAY_DEATH);
|
||||||
void Reset() override
|
BossAI::JustDied(killer);
|
||||||
|
float h = me->GetMapHeight(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
|
||||||
|
if (h != INVALID_HEIGHT && me->GetPositionZ() - h > 3.0f)
|
||||||
{
|
{
|
||||||
events.Reset();
|
me->UpdatePosition(me->GetPositionX(), me->GetPositionY(), h, me->GetOrientation(), true);
|
||||||
|
me->StopMovingOnCurrentPos();
|
||||||
|
me->DestroyForVisiblePlayers();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void JustEngagedWith(Unit* /*who*/) override
|
void KilledUnit(Unit* victim) override
|
||||||
{
|
{
|
||||||
DoZoneInCombat();
|
if (victim && victim->GetGUID() == me->GetGUID())
|
||||||
Talk(SAY_AGGRO);
|
return;
|
||||||
events.Reset();
|
Talk(SAY_SLAY);
|
||||||
events.RescheduleEvent(EVENT_SPELL_ARCANE_VACUUM, 30s);
|
}
|
||||||
events.RescheduleEvent(EVENT_SPELL_BLIZZARD, 5s, 10s);
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_TAIL_SWEEP, 15s, 20s);
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_UNCONTROLLABLE_ENERGY, 5s, 8s);
|
|
||||||
if (IsHeroic())
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_MANA_DESTRUCTION, 20s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
|
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||||
{
|
|
||||||
if (!target || !spell)
|
|
||||||
return;
|
|
||||||
switch (spell->Id)
|
|
||||||
{
|
|
||||||
case SPELL_ARCANE_VACUUM:
|
|
||||||
target->NearTeleportTo(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10.0f, target->GetOrientation());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
void EnterEvadeMode(EvadeReason why) override
|
||||||
{
|
{
|
||||||
if (!UpdateVictim())
|
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||||
return;
|
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
|
_EnterEvadeMode(why);
|
||||||
events.Update(diff);
|
}
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_ARCANE_VACUUM:
|
|
||||||
me->CastSpell((Unit*)nullptr, SPELL_ARCANE_VACUUM, false);
|
|
||||||
DoResetThreatList();
|
|
||||||
me->SetControlled(true, UNIT_STATE_ROOT);
|
|
||||||
me->setAttackTimer(BASE_ATTACK, 3000);
|
|
||||||
events.Repeat(30s);
|
|
||||||
events.ScheduleEvent(EVENT_UNROOT, 3s);
|
|
||||||
break;
|
|
||||||
case EVENT_UNROOT:
|
|
||||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_BLIZZARD:
|
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 45.0f, true))
|
|
||||||
me->CastSpell(target, SPELL_BLIZZARD, false);
|
|
||||||
events.Repeat(15s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_MANA_DESTRUCTION:
|
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
|
|
||||||
me->CastSpell(target, SPELL_MANA_DESTRUCTION, false);
|
|
||||||
events.Repeat(20s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_TAIL_SWEEP:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_TAIL_SWEEP, false);
|
|
||||||
events.Repeat(15s, 20s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_UNCONTROLLABLE_ENERGY:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_UNCONTROLLABLE_ENERGY, false);
|
|
||||||
events.Repeat(20s, 25s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
|
||||||
{
|
|
||||||
Talk(SAY_DEATH);
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetData(DATA_BOSS_DIED, 0);
|
|
||||||
float h = me->GetMapHeight(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
|
|
||||||
if (h != INVALID_HEIGHT && me->GetPositionZ() - h > 3.0f)
|
|
||||||
{
|
|
||||||
me->UpdatePosition(me->GetPositionX(), me->GetPositionY(), h, me->GetOrientation(), true); // move to ground
|
|
||||||
me->StopMovingOnCurrentPos();
|
|
||||||
me->DestroyForVisiblePlayers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KilledUnit(Unit* victim) override
|
|
||||||
{
|
|
||||||
if (victim && victim->GetGUID() == me->GetGUID())
|
|
||||||
return;
|
|
||||||
Talk(SAY_SLAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
|
||||||
|
|
||||||
void EnterEvadeMode(EvadeReason why) override
|
|
||||||
{
|
|
||||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
|
||||||
ScriptedAI::EnterEvadeMode(why);
|
|
||||||
events.Reset();
|
|
||||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetData(DATA_FAILED, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_cyanigosa()
|
void AddSC_boss_cyanigosa()
|
||||||
{
|
{
|
||||||
new boss_cyanigosa();
|
RegisterVioletHoldCreatureAI(boss_cyanigosa);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ enum eSpells
|
|||||||
SPELL_BREAK_BONDS = 59463,
|
SPELL_BREAK_BONDS = 59463,
|
||||||
SPELL_CHAIN_HEAL = 54481,
|
SPELL_CHAIN_HEAL = 54481,
|
||||||
SPELL_EARTH_SHIELD = 54479,
|
SPELL_EARTH_SHIELD = 54479,
|
||||||
//SPELL_EARTH_SHIELD_TRIGGERED_N = 54480,
|
|
||||||
//SPELL_EARTH_SHIELD_TRIGGERED_H = 59472,
|
|
||||||
SPELL_EARTH_SHOCK = 54511,
|
SPELL_EARTH_SHOCK = 54511,
|
||||||
SPELL_LIGHTNING_BOLT = 53044,
|
SPELL_LIGHTNING_BOLT = 53044,
|
||||||
SPELL_STORMSTRIKE = 51876,
|
SPELL_STORMSTRIKE = 51876,
|
||||||
@@ -53,164 +51,120 @@ enum eEvents
|
|||||||
EVENT_SPELL_STORMSTRIKE,
|
EVENT_SPELL_STORMSTRIKE,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_erekem : public CreatureScript
|
struct boss_erekem : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_erekem(Creature* c) : BossAI(c, BOSS_EREKEM) { }
|
||||||
boss_erekem() : CreatureScript("boss_erekem") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* pCreature) const override
|
void JustEngagedWith(Unit* who) override
|
||||||
{
|
{
|
||||||
return GetVioletHoldAI<boss_erekemAI>(pCreature);
|
BossAI::JustEngagedWith(who);
|
||||||
|
Talk(SAY_AGGRO);
|
||||||
|
DoCastSelf(SPELL_EARTH_SHIELD);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_BLOODLUST, 15s);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_BREAK_BONDS, 9s, 14s);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_CHAIN_HEAL, 0ms);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_EARTH_SHIELD, 20s);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_EARTH_SHOCK, 2s, 8s);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_LIGHTNING_BOLT, 5s, 10s);
|
||||||
|
if (IsHeroic())
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_STORMSTRIKE, 3s);
|
||||||
|
|
||||||
|
if (Creature* c = instance->instance->GetCreature(instance->GetGuidData(DATA_EREKEM_GUARD_1_GUID)))
|
||||||
|
if (!c->IsInCombat())
|
||||||
|
c->AI()->AttackStart(who);
|
||||||
|
if (Creature* c = instance->instance->GetCreature(instance->GetGuidData(DATA_EREKEM_GUARD_2_GUID)))
|
||||||
|
if (!c->IsInCombat())
|
||||||
|
c->AI()->AttackStart(who);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct boss_erekemAI : public ScriptedAI
|
void ExecuteEvent(uint32 eventId) override
|
||||||
{
|
{
|
||||||
boss_erekemAI(Creature* c) : ScriptedAI(c)
|
switch (eventId)
|
||||||
{
|
{
|
||||||
pInstance = c->GetInstanceScript();
|
case EVENT_SPELL_BLOODLUST:
|
||||||
}
|
DoCastAOE(SPELL_BLOODLUST);
|
||||||
|
events.Repeat(35s, 45s);
|
||||||
|
break;
|
||||||
|
case EVENT_SPELL_BREAK_BONDS:
|
||||||
|
DoCastAOE(SPELL_BREAK_BONDS);
|
||||||
|
events.Repeat(16s, 22s);
|
||||||
|
break;
|
||||||
|
case EVENT_SPELL_CHAIN_HEAL:
|
||||||
|
if (ObjectGuid targetGuid = GetChainHealTargetGuid())
|
||||||
|
{
|
||||||
|
if (Creature* target = instance->instance->GetCreature(targetGuid))
|
||||||
|
DoCast(target, SPELL_CHAIN_HEAL);
|
||||||
|
|
||||||
InstanceScript* pInstance;
|
Creature* guard1 = instance->instance->GetCreature(instance->GetGuidData(DATA_EREKEM_GUARD_1_GUID));
|
||||||
EventMap events;
|
Creature* guard2 = instance->instance->GetCreature(instance->GetGuidData(DATA_EREKEM_GUARD_2_GUID));
|
||||||
|
if ((guard1 && !guard1->IsAlive()) || (guard2 && !guard2->IsAlive()))
|
||||||
void Reset() override
|
|
||||||
{
|
|
||||||
events.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustEngagedWith(Unit* who) override
|
|
||||||
{
|
|
||||||
DoZoneInCombat();
|
|
||||||
Talk(SAY_AGGRO);
|
|
||||||
DoCast(me, SPELL_EARTH_SHIELD);
|
|
||||||
events.Reset();
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_BLOODLUST, 15s);
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_BREAK_BONDS, 9s, 14s);
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_CHAIN_HEAL, 0ms);
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_EARTH_SHIELD, 20s);
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_EARTH_SHOCK, 2s, 8s);
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_LIGHTNING_BOLT, 5s, 10s);
|
|
||||||
if (IsHeroic())
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_STORMSTRIKE, 3s);
|
|
||||||
|
|
||||||
if (Creature* c = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_EREKEM_GUARD_1_GUID)))
|
|
||||||
if (!c->IsInCombat())
|
|
||||||
c->AI()->AttackStart(who);
|
|
||||||
if (Creature* c = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_EREKEM_GUARD_2_GUID)))
|
|
||||||
if (!c->IsInCombat())
|
|
||||||
c->AI()->AttackStart(who);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
|
||||||
if (!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
events.Update(diff);
|
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_BLOODLUST:
|
|
||||||
me->CastSpell((Unit*)nullptr, SPELL_BLOODLUST, false);
|
|
||||||
events.Repeat(35s, 45s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_BREAK_BONDS:
|
|
||||||
me->CastSpell((Unit*)nullptr, SPELL_BREAK_BONDS, false);
|
|
||||||
events.Repeat(16s, 22s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_CHAIN_HEAL:
|
|
||||||
if (ObjectGuid TargetGUID = GetChainHealTargetGUID())
|
|
||||||
if (pInstance)
|
|
||||||
{
|
|
||||||
if (Creature* target = pInstance->instance->GetCreature(TargetGUID))
|
|
||||||
me->CastSpell(target, SPELL_CHAIN_HEAL, false);
|
|
||||||
|
|
||||||
Creature* pGuard1 = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_EREKEM_GUARD_1_GUID));
|
|
||||||
Creature* pGuard2 = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_EREKEM_GUARD_2_GUID));
|
|
||||||
if ((pGuard1 && !pGuard1->IsAlive()) || (pGuard2 && !pGuard2->IsAlive()))
|
|
||||||
{
|
|
||||||
events.Repeat(3s, 6s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
events.Repeat(8s, 11s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_EARTH_SHIELD:
|
|
||||||
me->CastSpell(me, SPELL_EARTH_SHIELD, false);
|
|
||||||
events.Repeat(20s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_EARTH_SHOCK:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_EARTH_SHOCK, false);
|
|
||||||
events.Repeat(8s, 13s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_LIGHTNING_BOLT:
|
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 35.0f, true))
|
|
||||||
me->CastSpell(target, SPELL_LIGHTNING_BOLT, false);
|
|
||||||
events.Repeat(15s, 25s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_STORMSTRIKE:
|
|
||||||
{
|
{
|
||||||
Creature* pGuard1 = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_EREKEM_GUARD_1_GUID));
|
events.Repeat(3s, 6s);
|
||||||
Creature* pGuard2 = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_EREKEM_GUARD_2_GUID));
|
break;
|
||||||
if (pGuard1 && !pGuard1->IsAlive() && pGuard2 && !pGuard2->IsAlive()) // both dead
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_STORMSTRIKE, false);
|
|
||||||
events.Repeat(3s);
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
}
|
events.Repeat(8s, 11s);
|
||||||
|
break;
|
||||||
DoMeleeAttackIfReady();
|
case EVENT_SPELL_EARTH_SHIELD:
|
||||||
|
DoCastSelf(SPELL_EARTH_SHIELD);
|
||||||
|
events.Repeat(20s);
|
||||||
|
break;
|
||||||
|
case EVENT_SPELL_EARTH_SHOCK:
|
||||||
|
DoCastVictim(SPELL_EARTH_SHOCK);
|
||||||
|
events.Repeat(8s, 13s);
|
||||||
|
break;
|
||||||
|
case EVENT_SPELL_LIGHTNING_BOLT:
|
||||||
|
DoCastRandomTarget(SPELL_LIGHTNING_BOLT, 0, 35.0f);
|
||||||
|
events.Repeat(15s, 25s);
|
||||||
|
break;
|
||||||
|
case EVENT_SPELL_STORMSTRIKE:
|
||||||
|
{
|
||||||
|
Creature* guard1 = instance->instance->GetCreature(instance->GetGuidData(DATA_EREKEM_GUARD_1_GUID));
|
||||||
|
Creature* guard2 = instance->instance->GetCreature(instance->GetGuidData(DATA_EREKEM_GUARD_2_GUID));
|
||||||
|
if (guard1 && !guard1->IsAlive() && guard2 && !guard2->IsAlive())
|
||||||
|
DoCastVictim(SPELL_STORMSTRIKE);
|
||||||
|
events.Repeat(3s);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
void JustDied(Unit* killer) override
|
||||||
{
|
{
|
||||||
Talk(SAY_DEATH);
|
Talk(SAY_DEATH);
|
||||||
if (pInstance)
|
BossAI::JustDied(killer);
|
||||||
pInstance->SetData(DATA_BOSS_DIED, 0);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void KilledUnit(Unit* victim) override
|
void KilledUnit(Unit* victim) override
|
||||||
{
|
{
|
||||||
if (victim && victim->GetGUID() == me->GetGUID())
|
if (victim && victim->GetGUID() == me->GetGUID())
|
||||||
return;
|
return;
|
||||||
Talk(SAY_SLAY);
|
Talk(SAY_SLAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||||
|
|
||||||
void EnterEvadeMode(EvadeReason why) override
|
void EnterEvadeMode(EvadeReason why) override
|
||||||
{
|
{
|
||||||
ScriptedAI::EnterEvadeMode(why);
|
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
events.Reset();
|
_EnterEvadeMode(why);
|
||||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
}
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetData(DATA_FAILED, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectGuid GetChainHealTargetGUID()
|
|
||||||
{
|
|
||||||
if (HealthBelowPct(85))
|
|
||||||
return me->GetGUID();
|
|
||||||
|
|
||||||
if (pInstance)
|
|
||||||
{
|
|
||||||
if (Creature* c = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_EREKEM_GUARD_1_GUID)))
|
|
||||||
if (c->IsAlive() && !c->HealthAbovePct(75))
|
|
||||||
return c->GetGUID();
|
|
||||||
|
|
||||||
if (Creature* c = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_EREKEM_GUARD_2_GUID)))
|
|
||||||
if (c->IsAlive() && !c->HealthAbovePct(75))
|
|
||||||
return c->GetGUID();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ObjectGuid GetChainHealTargetGuid()
|
||||||
|
{
|
||||||
|
if (HealthBelowPct(85))
|
||||||
return me->GetGUID();
|
return me->GetGUID();
|
||||||
}
|
|
||||||
};
|
if (Creature* c = instance->instance->GetCreature(instance->GetGuidData(DATA_EREKEM_GUARD_1_GUID)))
|
||||||
|
if (c->IsAlive() && !c->HealthAbovePct(75))
|
||||||
|
return c->GetGUID();
|
||||||
|
|
||||||
|
if (Creature* c = instance->instance->GetCreature(instance->GetGuidData(DATA_EREKEM_GUARD_2_GUID)))
|
||||||
|
if (c->IsAlive() && !c->HealthAbovePct(75))
|
||||||
|
return c->GetGUID();
|
||||||
|
|
||||||
|
return me->GetGUID();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GuardSpells
|
enum GuardSpells
|
||||||
@@ -227,81 +181,69 @@ enum eGuardEvents
|
|||||||
EVENT_SPELL_STRIKE
|
EVENT_SPELL_STRIKE
|
||||||
};
|
};
|
||||||
|
|
||||||
class npc_erekem_guard : public CreatureScript
|
struct npc_erekem_guard : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
npc_erekem_guard(Creature* c) : ScriptedAI(c)
|
||||||
npc_erekem_guard() : CreatureScript("npc_erekem_guard") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* pCreature) const override
|
|
||||||
{
|
{
|
||||||
return GetVioletHoldAI<npc_erekem_guardAI>(pCreature);
|
_instance = c->GetInstanceScript();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct npc_erekem_guardAI : public ScriptedAI
|
void Reset() override
|
||||||
{
|
{
|
||||||
npc_erekem_guardAI(Creature* c) : ScriptedAI(c)
|
_events.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JustEngagedWith(Unit* who) override
|
||||||
|
{
|
||||||
|
DoZoneInCombat();
|
||||||
|
_events.Reset();
|
||||||
|
_events.RescheduleEvent(EVENT_SPELL_GUSHING_WOUND, 1s, 3s);
|
||||||
|
_events.RescheduleEvent(EVENT_SPELL_HOWLING_SCREECH, 8s, 13s);
|
||||||
|
_events.RescheduleEvent(EVENT_SPELL_STRIKE, 4s, 8s);
|
||||||
|
|
||||||
|
if (Creature* c = _instance->GetCreature(BOSS_EREKEM))
|
||||||
|
if (!c->IsInCombat())
|
||||||
|
c->AI()->AttackStart(who);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
if (!UpdateVictim())
|
||||||
|
return;
|
||||||
|
|
||||||
|
_events.Update(diff);
|
||||||
|
|
||||||
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (_events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
pInstance = c->GetInstanceScript();
|
case EVENT_SPELL_GUSHING_WOUND:
|
||||||
|
DoCastVictim(SPELL_GUSHING_WOUND);
|
||||||
|
_events.Repeat(7s, 12s);
|
||||||
|
break;
|
||||||
|
case EVENT_SPELL_HOWLING_SCREECH:
|
||||||
|
DoCastVictim(SPELL_HOWLING_SCREECH);
|
||||||
|
_events.Repeat(8s, 13s);
|
||||||
|
break;
|
||||||
|
case EVENT_SPELL_STRIKE:
|
||||||
|
DoCastVictim(SPELL_STRIKE);
|
||||||
|
_events.Repeat(4s, 8s);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstanceScript* pInstance;
|
DoMeleeAttackIfReady();
|
||||||
EventMap events;
|
}
|
||||||
|
|
||||||
void Reset() override
|
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||||
{
|
|
||||||
events.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustEngagedWith(Unit* who) override
|
private:
|
||||||
{
|
InstanceScript* _instance;
|
||||||
DoZoneInCombat();
|
EventMap _events;
|
||||||
events.Reset();
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_GUSHING_WOUND, 1s, 3s);
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_HOWLING_SCREECH, 8s, 13s);
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_STRIKE, 4s, 8s);
|
|
||||||
|
|
||||||
if (Creature* c = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_EREKEM_GUID)))
|
|
||||||
if (!c->IsInCombat())
|
|
||||||
c->AI()->AttackStart(who);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
|
||||||
if (!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
events.Update(diff);
|
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_GUSHING_WOUND:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_GUSHING_WOUND, false);
|
|
||||||
events.Repeat(7s, 12s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_HOWLING_SCREECH:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_HOWLING_SCREECH, false);
|
|
||||||
events.Repeat(8s, 13s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_STRIKE:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_STRIKE, false);
|
|
||||||
events.Repeat(4s, 8s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_erekem()
|
void AddSC_boss_erekem()
|
||||||
{
|
{
|
||||||
new boss_erekem();
|
RegisterVioletHoldCreatureAI(boss_erekem);
|
||||||
new npc_erekem_guard();
|
RegisterVioletHoldCreatureAI(npc_erekem_guard);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,302 +58,278 @@ enum eSpells
|
|||||||
SPELL_WATER_BLAST = 54237,
|
SPELL_WATER_BLAST = 54237,
|
||||||
SPELL_WATER_BOLT_VOLLEY = 54241,
|
SPELL_WATER_BOLT_VOLLEY = 54241,
|
||||||
|
|
||||||
SPELL_SPLASH = 59516, // casted by globule upon death
|
SPELL_SPLASH = 59516,
|
||||||
SPELL_WATER_GLOBULE = 54268, // casted when hit by visual
|
SPELL_WATER_GLOBULE = 54268,
|
||||||
SPELL_CREATE_GLOBULE_VISUAL = 54260, // tar 25
|
SPELL_CREATE_GLOBULE_VISUAL = 54260,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_ichoron : public CreatureScript
|
enum eEvents
|
||||||
{
|
{
|
||||||
public:
|
EVENT_WATER_BOLT_VOLLEY = 1,
|
||||||
boss_ichoron() : CreatureScript("boss_ichoron") { }
|
EVENT_DRAINED_CHECK,
|
||||||
|
};
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* pCreature) const override
|
struct boss_ichoron : public BossAI
|
||||||
|
{
|
||||||
|
boss_ichoron(Creature* c) : BossAI(c, BOSS_ICHORON) { }
|
||||||
|
|
||||||
|
void Reset() override
|
||||||
{
|
{
|
||||||
return GetVioletHoldAI<boss_ichoronAI>(pCreature);
|
BossAI::Reset();
|
||||||
|
_isExploded = false;
|
||||||
|
_isFrenzy = false;
|
||||||
|
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||||
|
me->SetDisplayId(me->GetNativeDisplayId());
|
||||||
}
|
}
|
||||||
|
|
||||||
struct boss_ichoronAI : public ScriptedAI
|
void DoAction(int32 param) override
|
||||||
{
|
{
|
||||||
boss_ichoronAI(Creature* c) : ScriptedAI(c), globules(me)
|
if (!me->IsAlive())
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (param)
|
||||||
{
|
{
|
||||||
pInstance = c->GetInstanceScript();
|
case ACTION_WATER_ELEMENT_HIT:
|
||||||
|
instance->SetData(DATA_ACHIEV, 0);
|
||||||
|
me->ModifyHealth(int32(me->CountPctFromMaxHealth(1)));
|
||||||
|
if (_isExploded)
|
||||||
|
DoExplodeCompleted();
|
||||||
|
break;
|
||||||
|
case ACTION_WATER_ELEMENT_KILLED:
|
||||||
|
uint32 damage = me->CountPctFromMaxHealth(3);
|
||||||
|
damage = std::min(damage, me->GetHealth() - 1);
|
||||||
|
me->ModifyHealth(-int32(damage));
|
||||||
|
me->LowerPlayerDamageReq(damage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoExplodeCompleted()
|
||||||
|
{
|
||||||
|
_isExploded = false;
|
||||||
|
me->RemoveAura(SPELL_DRAINED);
|
||||||
|
if (!HealthBelowPct(25))
|
||||||
|
{
|
||||||
|
Talk(SAY_BUBBLE);
|
||||||
|
DoCastSelf(SPELL_PROTECTIVE_BUBBLE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
InstanceScript* pInstance;
|
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||||
SummonList globules;
|
me->SetDisplayId(me->GetNativeDisplayId());
|
||||||
bool bIsExploded;
|
}
|
||||||
bool bIsFrenzy;
|
|
||||||
uint32 uiWaterBoltVolleyTimer;
|
|
||||||
uint32 uiDrainedTimer;
|
|
||||||
|
|
||||||
void Reset() override
|
void IchoronDoCastToAllHostilePlayers(uint32 spellId, bool triggered)
|
||||||
|
{
|
||||||
|
Map::PlayerList const& playerList = me->GetMap()->GetPlayers();
|
||||||
|
if (playerList.IsEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (Map::PlayerList::const_iterator i = playerList.begin(); i != playerList.end(); ++i)
|
||||||
|
if (Player* plr = i->GetSource())
|
||||||
|
DoCast(plr, spellId, triggered);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JustEngagedWith(Unit* who) override
|
||||||
|
{
|
||||||
|
_isExploded = false;
|
||||||
|
_isFrenzy = false;
|
||||||
|
BossAI::JustEngagedWith(who);
|
||||||
|
Talk(SAY_AGGRO);
|
||||||
|
DoCastSelf(SPELL_PROTECTIVE_BUBBLE, true);
|
||||||
|
events.RescheduleEvent(EVENT_WATER_BOLT_VOLLEY, 7s, 12s);
|
||||||
|
instance->SetData(DATA_ACHIEV, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
if (!UpdateVictim())
|
||||||
|
return;
|
||||||
|
|
||||||
|
events.Update(diff);
|
||||||
|
|
||||||
|
if (!_isFrenzy && !_isExploded && HealthBelowPct(25))
|
||||||
{
|
{
|
||||||
globules.DespawnAll();
|
Talk(SAY_ENRAGE);
|
||||||
bIsExploded = false;
|
DoCastSelf(SPELL_FRENZY, true);
|
||||||
bIsFrenzy = false;
|
_isFrenzy = true;
|
||||||
uiDrainedTimer = 15000;
|
|
||||||
uiWaterBoltVolleyTimer = urand(7000, 12000);
|
|
||||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
|
||||||
me->SetDisplayId(me->GetNativeDisplayId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoAction(int32 param) override
|
if (!_isFrenzy)
|
||||||
{
|
{
|
||||||
if (!me->IsAlive())
|
if (!_isExploded)
|
||||||
return;
|
|
||||||
|
|
||||||
switch (param)
|
|
||||||
{
|
{
|
||||||
case ACTION_WATER_ELEMENT_HIT:
|
if (!me->HasAura(SPELL_PROTECTIVE_BUBBLE))
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetData(DATA_ACHIEV, 0);
|
|
||||||
me->ModifyHealth(int32(me->CountPctFromMaxHealth(1)));
|
|
||||||
if (bIsExploded)
|
|
||||||
DoExplodeCompleted();
|
|
||||||
break;
|
|
||||||
case ACTION_WATER_ELEMENT_KILLED:
|
|
||||||
uint32 damage = me->CountPctFromMaxHealth(3);
|
|
||||||
damage = std::min(damage, me->GetHealth() - 1);
|
|
||||||
me->ModifyHealth(-int32(damage));
|
|
||||||
me->LowerPlayerDamageReq(damage);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoExplodeCompleted()
|
|
||||||
{
|
|
||||||
bIsExploded = false;
|
|
||||||
me->RemoveAura(SPELL_DRAINED);
|
|
||||||
if (!HealthBelowPct(25))
|
|
||||||
{
|
|
||||||
Talk(SAY_BUBBLE);
|
|
||||||
me->CastSpell(me, SPELL_PROTECTIVE_BUBBLE, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
|
||||||
me->SetDisplayId(me->GetNativeDisplayId());
|
|
||||||
}
|
|
||||||
|
|
||||||
void IchoronDoCastToAllHostilePlayers(uint32 spellId, bool triggered)
|
|
||||||
{
|
|
||||||
Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers();
|
|
||||||
if (PlayerList.IsEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
|
|
||||||
if (Player* plr = i->GetSource())
|
|
||||||
me->CastSpell(plr, spellId, triggered);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustEngagedWith(Unit* /*who*/) override
|
|
||||||
{
|
|
||||||
bIsExploded = false;
|
|
||||||
bIsFrenzy = false;
|
|
||||||
uiDrainedTimer = 15000;
|
|
||||||
uiWaterBoltVolleyTimer = urand(7000, 12000);
|
|
||||||
DoZoneInCombat();
|
|
||||||
Talk(SAY_AGGRO);
|
|
||||||
me->CastSpell(me, SPELL_PROTECTIVE_BUBBLE, true);
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetData(DATA_ACHIEV, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 uiDiff) override
|
|
||||||
{
|
|
||||||
if (!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!bIsFrenzy && !bIsExploded && HealthBelowPct(25))
|
|
||||||
{
|
|
||||||
Talk(SAY_ENRAGE);
|
|
||||||
me->CastSpell(me, SPELL_FRENZY, true);
|
|
||||||
bIsFrenzy = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bIsFrenzy)
|
|
||||||
{
|
|
||||||
if (!bIsExploded)
|
|
||||||
{
|
{
|
||||||
if (!me->HasAura(SPELL_PROTECTIVE_BUBBLE))
|
me->InterruptNonMeleeSpells(false);
|
||||||
|
Talk(SAY_SHATTER);
|
||||||
|
DoZoneInCombat();
|
||||||
|
IchoronDoCastToAllHostilePlayers(SPELL_WATER_BLAST, true);
|
||||||
|
DoCastSelf(SPELL_DRAINED, true);
|
||||||
|
_isExploded = true;
|
||||||
|
events.CancelEvent(EVENT_WATER_BOLT_VOLLEY);
|
||||||
|
events.RescheduleEvent(EVENT_DRAINED_CHECK, 15s);
|
||||||
|
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||||
|
me->SetDisplayId(11686);
|
||||||
|
for (uint8 i = 0; i < MAX_SPAWN_LOC; ++i)
|
||||||
{
|
{
|
||||||
me->InterruptNonMeleeSpells(false);
|
float angle = rand_norm() * 2 * M_PI;
|
||||||
Talk(SAY_SHATTER);
|
Position p1(SpawnLoc[i]), p2(SpawnLoc[i]);
|
||||||
DoZoneInCombat();
|
p1.m_positionX += 2.5f * cos(angle);
|
||||||
IchoronDoCastToAllHostilePlayers(SPELL_WATER_BLAST, true);
|
p1.m_positionY += 2.5f * std::sin(angle);
|
||||||
me->CastSpell(me, SPELL_DRAINED, true);
|
p2.m_positionX -= 2.5f * cos(angle);
|
||||||
bIsExploded = true;
|
p2.m_positionY -= 2.5f * std::sin(angle);
|
||||||
uiDrainedTimer = 15000;
|
DoSummon(NPC_ICHOR_GLOBULE, p1, 60000, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN);
|
||||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
DoSummon(NPC_ICHOR_GLOBULE, p2, 60000, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN);
|
||||||
me->SetDisplayId(11686);
|
|
||||||
for (uint8 i = 0; i < MAX_SPAWN_LOC; ++i)
|
|
||||||
{
|
|
||||||
float angle = rand_norm() * 2 * M_PI;
|
|
||||||
Position p1(SpawnLoc[i]), p2(SpawnLoc[i]);
|
|
||||||
p1.m_positionX += 2.5f * cos(angle);
|
|
||||||
p1.m_positionY += 2.5f * std::sin(angle);
|
|
||||||
p2.m_positionX -= 2.5f * cos(angle);
|
|
||||||
p2.m_positionY -= 2.5f * std::sin(angle);
|
|
||||||
DoSummon(NPC_ICHOR_GLOBULE, p1, 60000, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN);
|
|
||||||
DoSummon(NPC_ICHOR_GLOBULE, p2, 60000, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (events.ExecuteEvent() == EVENT_DRAINED_CHECK)
|
||||||
|
DoExplodeCompleted();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (uiDrainedTimer <= uiDiff)
|
bool isWaterElementsAlive = false;
|
||||||
DoExplodeCompleted();
|
if (!summons.empty())
|
||||||
else
|
|
||||||
{
|
{
|
||||||
uiDrainedTimer -= uiDiff;
|
for (ObjectGuid const& guid : summons)
|
||||||
|
if (Creature* temp = ObjectAccessor::GetCreature(*me, guid))
|
||||||
bool bIsWaterElementsAlive = false;
|
if (temp->IsAlive())
|
||||||
if (!globules.empty())
|
{
|
||||||
{
|
isWaterElementsAlive = true;
|
||||||
for (ObjectGuid const& guid : globules)
|
break;
|
||||||
if (Creature* pTemp = ObjectAccessor::GetCreature(*me, guid))
|
}
|
||||||
if (pTemp->IsAlive())
|
|
||||||
{
|
|
||||||
bIsWaterElementsAlive = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bIsWaterElementsAlive)
|
|
||||||
DoExplodeCompleted();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isWaterElementsAlive)
|
||||||
|
DoExplodeCompleted();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bIsExploded)
|
|
||||||
{
|
|
||||||
if (uiWaterBoltVolleyTimer <= uiDiff)
|
|
||||||
{
|
|
||||||
me->CastSpell((Unit*)nullptr, SPELL_WATER_BOLT_VOLLEY, false);
|
|
||||||
uiWaterBoltVolleyTimer = urand(10000, 15000);
|
|
||||||
}
|
|
||||||
else uiWaterBoltVolleyTimer -= uiDiff;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustSummoned(Creature* pSummoned) override
|
if (!_isExploded)
|
||||||
{
|
{
|
||||||
if (pSummoned)
|
if (events.ExecuteEvent() == EVENT_WATER_BOLT_VOLLEY)
|
||||||
{
|
{
|
||||||
pSummoned->SetSpeed(MOVE_RUN, 0.3f);
|
DoCastAOE(SPELL_WATER_BOLT_VOLLEY);
|
||||||
pSummoned->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
events.Repeat(10s, 15s);
|
||||||
pSummoned->GetMotionMaster()->MoveFollow(me, 0, 0, MOTION_SLOT_ACTIVE, false, false);
|
|
||||||
me->CastSpell(pSummoned, SPELL_CREATE_GLOBULE_VISUAL, true); // triggered should ignore los
|
|
||||||
globules.Summon(pSummoned);
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetGuidData(DATA_ADD_TRASH_MOB, pSummoned->GetGUID());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SummonedCreatureDespawn(Creature* pSummoned) override
|
DoMeleeAttackIfReady();
|
||||||
{
|
|
||||||
if (pSummoned)
|
|
||||||
{
|
|
||||||
globules.Despawn(pSummoned);
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetGuidData(DATA_DELETE_TRASH_MOB, pSummoned->GetGUID());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
|
||||||
{
|
|
||||||
Talk(SAY_DEATH);
|
|
||||||
bIsExploded = false;
|
|
||||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
|
||||||
me->SetDisplayId(me->GetNativeDisplayId());
|
|
||||||
globules.DespawnAll();
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetData(DATA_BOSS_DIED, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KilledUnit(Unit* victim) override
|
|
||||||
{
|
|
||||||
if (victim && victim->GetGUID() == me->GetGUID())
|
|
||||||
return;
|
|
||||||
Talk(SAY_SLAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
|
||||||
|
|
||||||
void EnterEvadeMode(EvadeReason why) override
|
|
||||||
{
|
|
||||||
ScriptedAI::EnterEvadeMode(why);
|
|
||||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
|
||||||
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetData(DATA_FAILED, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
class npc_ichor_globule : public CreatureScript
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
npc_ichor_globule() : CreatureScript("npc_ichor_globule") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* pCreature) const override
|
|
||||||
{
|
|
||||||
return GetVioletHoldAI<npc_ichor_globuleAI>(pCreature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct npc_ichor_globuleAI : public ScriptedAI
|
void JustSummoned(Creature* summoned) override
|
||||||
{
|
{
|
||||||
npc_ichor_globuleAI(Creature* c) : ScriptedAI(c)
|
if (summoned)
|
||||||
{
|
{
|
||||||
pInstance = c->GetInstanceScript();
|
summoned->SetSpeed(MOVE_RUN, 0.3f);
|
||||||
uiRangeCheck_Timer = 1000;
|
summoned->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||||
|
summoned->GetMotionMaster()->MoveFollow(me, 0, 0, MOTION_SLOT_ACTIVE, false, false);
|
||||||
|
DoCast(summoned, SPELL_CREATE_GLOBULE_VISUAL, true);
|
||||||
|
BossAI::JustSummoned(summoned);
|
||||||
|
instance->SetGuidData(DATA_ADD_TRASH_MOB, summoned->GetGUID());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InstanceScript* pInstance;
|
void SummonedCreatureDespawn(Creature* summoned) override
|
||||||
uint32 uiRangeCheck_Timer;
|
{
|
||||||
|
if (summoned)
|
||||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
|
||||||
{
|
{
|
||||||
if (spell->Id == SPELL_CREATE_GLOBULE_VISUAL)
|
BossAI::SummonedCreatureDespawn(summoned);
|
||||||
me->CastSpell(me, SPELL_WATER_GLOBULE, true);
|
instance->SetGuidData(DATA_DELETE_TRASH_MOB, summoned->GetGUID());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateAI(uint32 uiDiff) override
|
void JustDied(Unit* killer) override
|
||||||
|
{
|
||||||
|
Talk(SAY_DEATH);
|
||||||
|
_isExploded = false;
|
||||||
|
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||||
|
me->SetDisplayId(me->GetNativeDisplayId());
|
||||||
|
BossAI::JustDied(killer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KilledUnit(Unit* victim) override
|
||||||
|
{
|
||||||
|
if (victim && victim->GetGUID() == me->GetGUID())
|
||||||
|
return;
|
||||||
|
Talk(SAY_SLAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||||
|
|
||||||
|
void EnterEvadeMode(EvadeReason why) override
|
||||||
|
{
|
||||||
|
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
|
_EnterEvadeMode(why);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _isExploded;
|
||||||
|
bool _isFrenzy;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum eGlobuleEvents
|
||||||
|
{
|
||||||
|
EVENT_RANGE_CHECK = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct npc_ichor_globule : public ScriptedAI
|
||||||
|
{
|
||||||
|
npc_ichor_globule(Creature* c) : ScriptedAI(c)
|
||||||
|
{
|
||||||
|
_instance = c->GetInstanceScript();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reset() override
|
||||||
|
{
|
||||||
|
_events.RescheduleEvent(EVENT_RANGE_CHECK, 1s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
||||||
|
{
|
||||||
|
if (spell->Id == SPELL_CREATE_GLOBULE_VISUAL)
|
||||||
|
DoCastSelf(SPELL_WATER_GLOBULE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
_events.Update(diff);
|
||||||
|
|
||||||
|
if (_events.ExecuteEvent() == EVENT_RANGE_CHECK)
|
||||||
{
|
{
|
||||||
if (uiRangeCheck_Timer < uiDiff)
|
if (Creature* ichoron = _instance->GetCreature(BOSS_ICHORON))
|
||||||
{
|
if (me->IsWithinDist(ichoron, 2.0f, false))
|
||||||
if (pInstance)
|
{
|
||||||
if (Creature* pIchoron = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_ICHORON_GUID)))
|
if (ichoron->AI())
|
||||||
if (me->IsWithinDist(pIchoron, 2.0f, false))
|
ichoron->AI()->DoAction(ACTION_WATER_ELEMENT_HIT);
|
||||||
{
|
me->DespawnOrUnsummon();
|
||||||
if (pIchoron->AI())
|
return;
|
||||||
pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_HIT);
|
}
|
||||||
me->DespawnOrUnsummon();
|
_events.Repeat(1s);
|
||||||
}
|
|
||||||
uiRangeCheck_Timer = 1000;
|
|
||||||
}
|
|
||||||
else uiRangeCheck_Timer -= uiDiff;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
void JustDied(Unit* /*killer*/) override
|
||||||
{
|
{
|
||||||
me->CastSpell(me, SPELL_SPLASH, true);
|
DoCastSelf(SPELL_SPLASH, true);
|
||||||
if (pInstance)
|
if (Creature* ichoron = _instance->GetCreature(BOSS_ICHORON))
|
||||||
if (Creature* pIchoron = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_ICHORON_GUID)))
|
if (ichoron->AI())
|
||||||
if (pIchoron->AI())
|
ichoron->AI()->DoAction(ACTION_WATER_ELEMENT_KILLED);
|
||||||
pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_KILLED);
|
me->DespawnOrUnsummon(2500ms);
|
||||||
me->DespawnOrUnsummon(2500ms);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void AttackStart(Unit* /*who*/) override {}
|
void AttackStart(Unit* /*who*/) override {}
|
||||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||||
};
|
|
||||||
|
private:
|
||||||
|
InstanceScript* _instance;
|
||||||
|
EventMap _events;
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_ichoron()
|
void AddSC_boss_ichoron()
|
||||||
{
|
{
|
||||||
new boss_ichoron();
|
RegisterVioletHoldCreatureAI(boss_ichoron);
|
||||||
new npc_ichor_globule();
|
RegisterVioletHoldCreatureAI(npc_ichor_globule);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,97 +35,53 @@ enum eEvents
|
|||||||
EVENT_SPELL_CAUTERIZING_FLAMES,
|
EVENT_SPELL_CAUTERIZING_FLAMES,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_lavanthor : public CreatureScript
|
struct boss_lavanthor : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_lavanthor(Creature* c) : BossAI(c, BOSS_LAVANTHOR) { }
|
||||||
boss_lavanthor() : CreatureScript("boss_lavanthor") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* pCreature) const override
|
void JustEngagedWith(Unit* who) override
|
||||||
{
|
{
|
||||||
return GetVioletHoldAI<boss_lavanthorAI>(pCreature);
|
BossAI::JustEngagedWith(who);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_FIREBOLT, 1s);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_FLAME_BREATH, 5s);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_LAVA_BURN, 10s);
|
||||||
|
if (IsHeroic())
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_CAUTERIZING_FLAMES, 3s);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct boss_lavanthorAI : public ScriptedAI
|
void ExecuteEvent(uint32 eventId) override
|
||||||
{
|
{
|
||||||
boss_lavanthorAI(Creature* c) : ScriptedAI(c)
|
switch (eventId)
|
||||||
{
|
{
|
||||||
pInstance = c->GetInstanceScript();
|
case EVENT_SPELL_FIREBOLT:
|
||||||
|
DoCastVictim(SPELL_FIREBOLT);
|
||||||
|
events.Repeat(5s, 13s);
|
||||||
|
break;
|
||||||
|
case EVENT_SPELL_FLAME_BREATH:
|
||||||
|
DoCastVictim(SPELL_FLAME_BREATH);
|
||||||
|
events.Repeat(10s, 15s);
|
||||||
|
break;
|
||||||
|
case EVENT_SPELL_LAVA_BURN:
|
||||||
|
DoCastVictim(SPELL_LAVA_BURN);
|
||||||
|
events.Repeat(14s, 20s);
|
||||||
|
break;
|
||||||
|
case EVENT_SPELL_CAUTERIZING_FLAMES:
|
||||||
|
DoCastAOE(SPELL_CAUTERIZING_FLAMES);
|
||||||
|
events.Repeat(10s, 16s);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InstanceScript* pInstance;
|
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||||
EventMap events;
|
|
||||||
|
|
||||||
void Reset() override
|
void EnterEvadeMode(EvadeReason why) override
|
||||||
{
|
{
|
||||||
events.Reset();
|
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
}
|
_EnterEvadeMode(why);
|
||||||
|
}
|
||||||
void JustEngagedWith(Unit* /*who*/) override
|
|
||||||
{
|
|
||||||
DoZoneInCombat();
|
|
||||||
events.Reset();
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_FIREBOLT, 1s);
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_FLAME_BREATH, 5s);
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_LAVA_BURN, 10s);
|
|
||||||
if (IsHeroic())
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_CAUTERIZING_FLAMES, 3s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
|
||||||
if (!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
events.Update(diff);
|
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_FIREBOLT:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_FIREBOLT, false);
|
|
||||||
events.Repeat(5s, 13s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_FLAME_BREATH:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_FLAME_BREATH, false);
|
|
||||||
events.Repeat(10s, 15s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_LAVA_BURN:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_LAVA_BURN, false);
|
|
||||||
events.Repeat(14s, 20s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_CAUTERIZING_FLAMES:
|
|
||||||
me->CastSpell((Unit*)nullptr, SPELL_FLAME_BREATH, false);
|
|
||||||
events.Repeat(10s, 16s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
|
||||||
{
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetData(DATA_BOSS_DIED, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
|
||||||
|
|
||||||
void EnterEvadeMode(EvadeReason why) override
|
|
||||||
{
|
|
||||||
ScriptedAI::EnterEvadeMode(why);
|
|
||||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
|
||||||
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetData(DATA_FAILED, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_lavanthor()
|
void AddSC_boss_lavanthor()
|
||||||
{
|
{
|
||||||
new boss_lavanthor();
|
RegisterVioletHoldCreatureAI(boss_lavanthor);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,7 @@
|
|||||||
enum eSpells
|
enum eSpells
|
||||||
{
|
{
|
||||||
SPELL_RAY_OF_SUFFERING = 54442,
|
SPELL_RAY_OF_SUFFERING = 54442,
|
||||||
//SPELL_RAY_OF_SUFFERING_TRIGGERED = 54417,
|
|
||||||
|
|
||||||
SPELL_RAY_OF_PAIN = 54438,
|
SPELL_RAY_OF_PAIN = 54438,
|
||||||
//SPELL_RAY_OF_PAIN_TRIGGERED_N = 54416,
|
|
||||||
//SPELL_RAY_OF_PAIN_TRIGGERED_H = 59525,
|
|
||||||
|
|
||||||
SPELL_CORROSIVE_SALIVA = 54527,
|
SPELL_CORROSIVE_SALIVA = 54527,
|
||||||
SPELL_OPTIC_LINK = 54396,
|
SPELL_OPTIC_LINK = 54396,
|
||||||
};
|
};
|
||||||
@@ -41,90 +36,46 @@ enum eEvents
|
|||||||
EVENT_SPELL_OPTIC_LINK,
|
EVENT_SPELL_OPTIC_LINK,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_moragg : public CreatureScript
|
struct boss_moragg : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_moragg(Creature* c) : BossAI(c, BOSS_MORAGG) { }
|
||||||
boss_moragg() : CreatureScript("boss_moragg") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* pCreature) const override
|
void JustEngagedWith(Unit* who) override
|
||||||
{
|
{
|
||||||
return GetVioletHoldAI<boss_moraggAI>(pCreature);
|
BossAI::JustEngagedWith(who);
|
||||||
|
DoCastSelf(SPELL_RAY_OF_SUFFERING, true);
|
||||||
|
DoCastSelf(SPELL_RAY_OF_PAIN, true);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_CORROSIVE_SALIVA, 4s, 6s);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_OPTIC_LINK, 10s, 11s);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct boss_moraggAI : public ScriptedAI
|
void ExecuteEvent(uint32 eventId) override
|
||||||
{
|
{
|
||||||
boss_moraggAI(Creature* c) : ScriptedAI(c)
|
switch (eventId)
|
||||||
{
|
{
|
||||||
pInstance = c->GetInstanceScript();
|
case EVENT_SPELL_CORROSIVE_SALIVA:
|
||||||
|
DoCastVictim(SPELL_CORROSIVE_SALIVA);
|
||||||
|
events.Repeat(8s, 10s);
|
||||||
|
break;
|
||||||
|
case EVENT_SPELL_OPTIC_LINK:
|
||||||
|
if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0, 40.0f, true))
|
||||||
|
{
|
||||||
|
DoCast(target, SPELL_OPTIC_LINK);
|
||||||
|
events.Repeat(18s, 21s);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
events.Repeat(5s);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InstanceScript* pInstance;
|
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||||
EventMap events;
|
|
||||||
|
|
||||||
void Reset() override
|
void EnterEvadeMode(EvadeReason why) override
|
||||||
{
|
{
|
||||||
events.Reset();
|
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
}
|
_EnterEvadeMode(why);
|
||||||
|
}
|
||||||
void JustEngagedWith(Unit* /*who*/) override
|
|
||||||
{
|
|
||||||
DoZoneInCombat();
|
|
||||||
me->CastSpell(me, SPELL_RAY_OF_SUFFERING, true);
|
|
||||||
me->CastSpell(me, SPELL_RAY_OF_PAIN, true);
|
|
||||||
events.Reset();
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_CORROSIVE_SALIVA, 4s, 6s);
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_OPTIC_LINK, 10s, 11s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
|
||||||
if (!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
events.Update(diff);
|
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_CORROSIVE_SALIVA:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_CORROSIVE_SALIVA, false);
|
|
||||||
events.Repeat(8s, 10s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_OPTIC_LINK:
|
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0, 40.0f, true))
|
|
||||||
{
|
|
||||||
me->CastSpell(target, SPELL_OPTIC_LINK, false);
|
|
||||||
events.Repeat(18s, 21s);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
events.Repeat(5s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
|
||||||
{
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetData(DATA_BOSS_DIED, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
|
||||||
|
|
||||||
void EnterEvadeMode(EvadeReason why) override
|
|
||||||
{
|
|
||||||
ScriptedAI::EnterEvadeMode(why);
|
|
||||||
events.Reset();
|
|
||||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetData(DATA_FAILED, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class spell_optic_link_aura : public AuraScript
|
class spell_optic_link_aura : public AuraScript
|
||||||
@@ -147,6 +98,6 @@ class spell_optic_link_aura : public AuraScript
|
|||||||
|
|
||||||
void AddSC_boss_moragg()
|
void AddSC_boss_moragg()
|
||||||
{
|
{
|
||||||
new boss_moragg();
|
RegisterVioletHoldCreatureAI(boss_moragg);
|
||||||
RegisterSpellScript(spell_optic_link_aura);
|
RegisterSpellScript(spell_optic_link_aura);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,8 +39,6 @@ enum eSpells
|
|||||||
SPELL_SUMMON_ETHEREAL_SPHERE_3 = 54138,
|
SPELL_SUMMON_ETHEREAL_SPHERE_3 = 54138,
|
||||||
|
|
||||||
SPELL_ARCANE_POWER = 54160
|
SPELL_ARCANE_POWER = 54160
|
||||||
//SPELL_SUMMON_PLAYERS = 54164, // not used
|
|
||||||
//SPELL_POWER_BALL_VISUAL = 54141,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum eEvents
|
enum eEvents
|
||||||
@@ -51,159 +49,114 @@ enum eEvents
|
|||||||
EVENT_CHECK_DISTANCE,
|
EVENT_CHECK_DISTANCE,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_xevozz : public CreatureScript
|
struct boss_xevozz : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_xevozz(Creature* c) : BossAI(c, BOSS_XEVOZZ) { }
|
||||||
boss_xevozz() : CreatureScript("boss_xevozz") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* pCreature) const override
|
void JustEngagedWith(Unit* who) override
|
||||||
{
|
{
|
||||||
return GetVioletHoldAI<boss_xevozzAI>(pCreature);
|
Talk(SAY_AGGRO);
|
||||||
|
BossAI::JustEngagedWith(who);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_ARCANE_BARRAGE_VOLLEY, 16s, 20s);
|
||||||
|
events.RescheduleEvent(EVENT_SUMMON_SPHERES, 10s);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct boss_xevozzAI : public ScriptedAI
|
void ExecuteEvent(uint32 eventId) override
|
||||||
{
|
{
|
||||||
boss_xevozzAI(Creature* c) : ScriptedAI(c), spheres(me)
|
switch (eventId)
|
||||||
{
|
{
|
||||||
pInstance = c->GetInstanceScript();
|
case EVENT_SPELL_ARCANE_BARRAGE_VOLLEY:
|
||||||
}
|
DoCastAOE(SPELL_ARCANE_BARRAGE_VOLLEY);
|
||||||
|
events.Repeat(20s);
|
||||||
InstanceScript* pInstance;
|
break;
|
||||||
EventMap events;
|
case EVENT_SPELL_ARCANE_BUFFET:
|
||||||
SummonList spheres;
|
DoCastVictim(SPELL_ARCANE_BUFFET);
|
||||||
|
break;
|
||||||
void Reset() override
|
case EVENT_SUMMON_SPHERES:
|
||||||
{
|
{
|
||||||
events.Reset();
|
Talk(SAY_SUMMON_ENERGY);
|
||||||
spheres.DespawnAll();
|
summons.DespawnAll();
|
||||||
}
|
uint32 entry1 = RAND(SPELL_SUMMON_ETHEREAL_SPHERE_1, SPELL_SUMMON_ETHEREAL_SPHERE_2, SPELL_SUMMON_ETHEREAL_SPHERE_3);
|
||||||
|
DoCastAOE(entry1, true);
|
||||||
void JustEngagedWith(Unit* /*who*/) override
|
if (IsHeroic())
|
||||||
{
|
|
||||||
Talk(SAY_AGGRO);
|
|
||||||
DoZoneInCombat();
|
|
||||||
events.Reset();
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_ARCANE_BARRAGE_VOLLEY, 16s, 20s);
|
|
||||||
events.RescheduleEvent(EVENT_SUMMON_SPHERES, 10s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
|
||||||
if (!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
events.Update(diff);
|
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_ARCANE_BARRAGE_VOLLEY:
|
|
||||||
me->CastSpell((Unit*)nullptr, SPELL_ARCANE_BARRAGE_VOLLEY, false);
|
|
||||||
events.Repeat(20s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_ARCANE_BUFFET:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_ARCANE_BUFFET, false);
|
|
||||||
break;
|
|
||||||
case EVENT_SUMMON_SPHERES:
|
|
||||||
{
|
{
|
||||||
Talk(SAY_SUMMON_ENERGY);
|
uint32 entry2;
|
||||||
spheres.DespawnAll();
|
do { entry2 = RAND(SPELL_SUMMON_ETHEREAL_SPHERE_1, SPELL_SUMMON_ETHEREAL_SPHERE_2, SPELL_SUMMON_ETHEREAL_SPHERE_3); }
|
||||||
uint32 entry1 = RAND(SPELL_SUMMON_ETHEREAL_SPHERE_1, SPELL_SUMMON_ETHEREAL_SPHERE_2, SPELL_SUMMON_ETHEREAL_SPHERE_3);
|
while (entry1 == entry2);
|
||||||
me->CastSpell((Unit*)nullptr, entry1, true);
|
DoCastAOE(entry2, true);
|
||||||
if (IsHeroic())
|
|
||||||
{
|
|
||||||
uint32 entry2;
|
|
||||||
do { entry2 = RAND(SPELL_SUMMON_ETHEREAL_SPHERE_1, SPELL_SUMMON_ETHEREAL_SPHERE_2, SPELL_SUMMON_ETHEREAL_SPHERE_3); }
|
|
||||||
while (entry1 == entry2);
|
|
||||||
me->CastSpell((Unit*)nullptr, entry2, true);
|
|
||||||
}
|
|
||||||
events.Repeat(45s);
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_ARCANE_BUFFET, 5s);
|
|
||||||
events.RescheduleEvent(EVENT_CHECK_DISTANCE, 6s);
|
|
||||||
}
|
}
|
||||||
break;
|
events.Repeat(45s);
|
||||||
case EVENT_CHECK_DISTANCE:
|
events.RescheduleEvent(EVENT_SPELL_ARCANE_BUFFET, 5s);
|
||||||
|
events.RescheduleEvent(EVENT_CHECK_DISTANCE, 6s);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EVENT_CHECK_DISTANCE:
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for (ObjectGuid const& guid : summons)
|
||||||
|
if (Creature* sphere = instance->instance->GetCreature(guid))
|
||||||
|
if (me->GetDistance(sphere) < 3.0f)
|
||||||
|
{
|
||||||
|
sphere->CastSpell(me, SPELL_ARCANE_POWER, false);
|
||||||
|
sphere->DespawnOrUnsummon(8s);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
if (found)
|
||||||
{
|
{
|
||||||
bool found = false;
|
Talk(SAY_CHARGED);
|
||||||
if (pInstance)
|
events.Repeat(9s);
|
||||||
for (ObjectGuid const& guid : spheres)
|
events.RescheduleEvent(EVENT_SUMMON_SPHERES, 10s);
|
||||||
if (Creature* c = pInstance->instance->GetCreature(guid))
|
|
||||||
if (me->GetDistance(c) < 3.0f)
|
|
||||||
{
|
|
||||||
c->CastSpell(me, SPELL_ARCANE_POWER, false);
|
|
||||||
c->DespawnOrUnsummon(8s);
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
if (found)
|
|
||||||
{
|
|
||||||
Talk(SAY_CHARGED);
|
|
||||||
events.Repeat(9s);
|
|
||||||
events.RescheduleEvent(EVENT_SUMMON_SPHERES, 10s);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
events.Repeat(2s);
|
|
||||||
}
|
}
|
||||||
break;
|
else
|
||||||
}
|
events.Repeat(2s);
|
||||||
|
}
|
||||||
DoMeleeAttackIfReady();
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void JustSummoned(Creature* pSummoned) override
|
void JustSummoned(Creature* summoned) override
|
||||||
|
{
|
||||||
|
if (summoned)
|
||||||
{
|
{
|
||||||
if (pSummoned)
|
summoned->GetMotionMaster()->MoveFollow(me, 0.0f, 0.0f, MOTION_SLOT_ACTIVE, true, false);
|
||||||
{
|
BossAI::JustSummoned(summoned);
|
||||||
pSummoned->GetMotionMaster()->MoveFollow(me, 0.0f, 0.0f, MOTION_SLOT_ACTIVE, true, false);
|
instance->SetGuidData(DATA_ADD_TRASH_MOB, summoned->GetGUID());
|
||||||
spheres.Summon(pSummoned);
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetGuidData(DATA_ADD_TRASH_MOB, pSummoned->GetGUID());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SummonedCreatureDespawn(Creature* pSummoned) override
|
void SummonedCreatureDespawn(Creature* summoned) override
|
||||||
|
{
|
||||||
|
if (summoned)
|
||||||
{
|
{
|
||||||
if (pSummoned)
|
BossAI::SummonedCreatureDespawn(summoned);
|
||||||
{
|
instance->SetGuidData(DATA_DELETE_TRASH_MOB, summoned->GetGUID());
|
||||||
spheres.Despawn(pSummoned);
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetGuidData(DATA_DELETE_TRASH_MOB, pSummoned->GetGUID());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
void JustDied(Unit* killer) override
|
||||||
{
|
{
|
||||||
Talk(SAY_DEATH);
|
Talk(SAY_DEATH);
|
||||||
spheres.DespawnAll();
|
BossAI::JustDied(killer);
|
||||||
if (pInstance)
|
}
|
||||||
pInstance->SetData(DATA_BOSS_DIED, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KilledUnit(Unit* pVictim) override
|
void KilledUnit(Unit* victim) override
|
||||||
{
|
{
|
||||||
if (pVictim && pVictim->GetGUID() == me->GetGUID())
|
if (victim && victim->GetGUID() == me->GetGUID())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Talk(SAY_SLAY);
|
Talk(SAY_SLAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||||
|
|
||||||
void EnterEvadeMode(EvadeReason why) override
|
void EnterEvadeMode(EvadeReason why) override
|
||||||
{
|
{
|
||||||
ScriptedAI::EnterEvadeMode(why);
|
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
events.Reset();
|
_EnterEvadeMode(why);
|
||||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
}
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetData(DATA_FAILED, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_xevozz()
|
void AddSC_boss_xevozz()
|
||||||
{
|
{
|
||||||
new boss_xevozz();
|
RegisterVioletHoldCreatureAI(boss_xevozz);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,12 +36,12 @@ enum eSpells
|
|||||||
SPELL_VOID_SHIFT = 54361,
|
SPELL_VOID_SHIFT = 54361,
|
||||||
SPELL_SUMMON_VOID_SENTRY = 54369,
|
SPELL_SUMMON_VOID_SENTRY = 54369,
|
||||||
SPELL_SUMMON_VOID_SENTRY_BALL = 58650,
|
SPELL_SUMMON_VOID_SENTRY_BALL = 58650,
|
||||||
|
|
||||||
//SPELL_ZURAMAT_ADD_2_N = 54342,
|
|
||||||
//SPELL_ZURAMAT_ADD_2_H = 59747,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NPC_VOID_SENTRY_BALL 29365
|
enum eCreatures
|
||||||
|
{
|
||||||
|
NPC_VOID_SENTRY_BALL = 29365,
|
||||||
|
};
|
||||||
|
|
||||||
enum eEvents
|
enum eEvents
|
||||||
{
|
{
|
||||||
@@ -50,208 +50,154 @@ enum eEvents
|
|||||||
EVENT_SPELL_SUMMON_VOID_SENTRY,
|
EVENT_SPELL_SUMMON_VOID_SENTRY,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_zuramat : public CreatureScript
|
enum eVoidSentryEvents
|
||||||
{
|
{
|
||||||
public:
|
EVENT_CHECK_SUMMONER = 1,
|
||||||
boss_zuramat() : CreatureScript("boss_zuramat") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* pCreature) const override
|
|
||||||
{
|
|
||||||
return GetVioletHoldAI<boss_zuramatAI>(pCreature);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct boss_zuramatAI : public ScriptedAI
|
|
||||||
{
|
|
||||||
boss_zuramatAI(Creature* c) : ScriptedAI(c), summons(me)
|
|
||||||
{
|
|
||||||
pInstance = c->GetInstanceScript();
|
|
||||||
}
|
|
||||||
|
|
||||||
InstanceScript* pInstance;
|
|
||||||
EventMap events;
|
|
||||||
SummonList summons;
|
|
||||||
|
|
||||||
void Reset() override
|
|
||||||
{
|
|
||||||
events.Reset();
|
|
||||||
summons.DespawnAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustEngagedWith(Unit* /*who*/) override
|
|
||||||
{
|
|
||||||
Talk(SAY_AGGRO);
|
|
||||||
DoZoneInCombat();
|
|
||||||
events.Reset();
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_SHROUD_OF_DARKNESS, 5s, 7s);
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_VOID_SHIFT, 23s, 25s);
|
|
||||||
events.RescheduleEvent(EVENT_SPELL_SUMMON_VOID_SENTRY, 10s);
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetData(DATA_ACHIEV, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
|
||||||
if (!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
events.Update(diff);
|
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_SHROUD_OF_DARKNESS:
|
|
||||||
me->CastSpell(me, SPELL_SHROUD_OF_DARKNESS, false);
|
|
||||||
Talk(SAY_SHIELD);
|
|
||||||
events.Repeat(20s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_VOID_SHIFT:
|
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
|
|
||||||
{
|
|
||||||
me->CastSpell(target, SPELL_VOID_SHIFT, false);
|
|
||||||
me->Whisper("Gaze... into the void.", LANG_UNIVERSAL, target->ToPlayer());
|
|
||||||
}
|
|
||||||
events.Repeat(18s, 22s);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_SUMMON_VOID_SENTRY:
|
|
||||||
me->CastSpell((Unit*)nullptr, SPELL_SUMMON_VOID_SENTRY, false);
|
|
||||||
events.Repeat(12s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
|
||||||
{
|
|
||||||
summons.DespawnAll();
|
|
||||||
Talk(SAY_DEATH);
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetData(DATA_BOSS_DIED, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KilledUnit(Unit* victim) override
|
|
||||||
{
|
|
||||||
if (victim && victim->GetGUID() == me->GetGUID())
|
|
||||||
return;
|
|
||||||
|
|
||||||
Talk(SAY_SLAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustSummoned(Creature* pSummoned) override
|
|
||||||
{
|
|
||||||
if (pSummoned)
|
|
||||||
{
|
|
||||||
summons.Summon(pSummoned);
|
|
||||||
pSummoned->SetPhaseMask(16, true);
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetGuidData(DATA_ADD_TRASH_MOB, pSummoned->GetGUID());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SummonedCreatureDespawn(Creature* pSummoned) override
|
|
||||||
{
|
|
||||||
if (pSummoned)
|
|
||||||
{
|
|
||||||
summons.Despawn(pSummoned);
|
|
||||||
if (pSummoned->IsAIEnabled)
|
|
||||||
pSummoned->AI()->DoAction(-1337);
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetGuidData(DATA_DELETE_TRASH_MOB, pSummoned->GetGUID());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
|
||||||
|
|
||||||
void EnterEvadeMode(EvadeReason why) override
|
|
||||||
{
|
|
||||||
ScriptedAI::EnterEvadeMode(why);
|
|
||||||
events.Reset();
|
|
||||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
|
||||||
if (pInstance)
|
|
||||||
pInstance->SetData(DATA_FAILED, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class npc_vh_void_sentry : public CreatureScript
|
struct boss_zuramat : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_zuramat(Creature* c) : BossAI(c, BOSS_ZURAMAT) { }
|
||||||
npc_vh_void_sentry() : CreatureScript("npc_vh_void_sentry") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* pCreature) const override
|
void JustEngagedWith(Unit* who) override
|
||||||
{
|
{
|
||||||
return GetVioletHoldAI<npc_vh_void_sentryAI>(pCreature);
|
Talk(SAY_AGGRO);
|
||||||
|
BossAI::JustEngagedWith(who);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_SHROUD_OF_DARKNESS, 5s, 7s);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_VOID_SHIFT, 23s, 25s);
|
||||||
|
events.RescheduleEvent(EVENT_SPELL_SUMMON_VOID_SENTRY, 10s);
|
||||||
|
instance->SetData(DATA_ACHIEV, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct npc_vh_void_sentryAI : public NullCreatureAI
|
void ExecuteEvent(uint32 eventId) override
|
||||||
{
|
{
|
||||||
npc_vh_void_sentryAI(Creature* c) : NullCreatureAI(c)
|
switch (eventId)
|
||||||
{
|
{
|
||||||
pInstance = c->GetInstanceScript();
|
case EVENT_SPELL_SHROUD_OF_DARKNESS:
|
||||||
SummonedGUID.Clear();
|
DoCastSelf(SPELL_SHROUD_OF_DARKNESS);
|
||||||
checkTimer = 5000;
|
Talk(SAY_SHIELD);
|
||||||
//me->CastSpell(me, SPELL_SUMMON_VOID_SENTRY_BALL, true);
|
events.Repeat(20s);
|
||||||
if (Creature* pSummoned = me->SummonCreature(NPC_VOID_SENTRY_BALL, *me, TEMPSUMMON_TIMED_DESPAWN, 300000))
|
break;
|
||||||
{
|
case EVENT_SPELL_VOID_SHIFT:
|
||||||
pSummoned->SetPhaseMask(1, true);
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
|
||||||
SummonedGUID = pSummoned->GetGUID();
|
{
|
||||||
pInstance->SetGuidData(DATA_ADD_TRASH_MOB, pSummoned->GetGUID());
|
DoCast(target, SPELL_VOID_SHIFT);
|
||||||
}
|
me->Whisper("Gaze... into the void.", LANG_UNIVERSAL, target->ToPlayer());
|
||||||
|
}
|
||||||
|
events.Repeat(18s, 22s);
|
||||||
|
break;
|
||||||
|
case EVENT_SPELL_SUMMON_VOID_SENTRY:
|
||||||
|
DoCastAOE(SPELL_SUMMON_VOID_SENTRY);
|
||||||
|
events.Repeat(12s);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InstanceScript* pInstance;
|
void JustDied(Unit* killer) override
|
||||||
ObjectGuid SummonedGUID;
|
{
|
||||||
uint16 checkTimer;
|
Talk(SAY_DEATH);
|
||||||
|
BossAI::JustDied(killer);
|
||||||
|
}
|
||||||
|
|
||||||
void DoAction(int32 a) override
|
void KilledUnit(Unit* victim) override
|
||||||
|
{
|
||||||
|
if (victim && victim->GetGUID() == me->GetGUID())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Talk(SAY_SLAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JustSummoned(Creature* summoned) override
|
||||||
|
{
|
||||||
|
if (summoned)
|
||||||
{
|
{
|
||||||
if (a == -1337)
|
BossAI::JustSummoned(summoned);
|
||||||
if (Creature* c = pInstance->instance->GetCreature(SummonedGUID))
|
summoned->SetPhaseMask(16, true);
|
||||||
c->DespawnOrUnsummon();
|
instance->SetGuidData(DATA_ADD_TRASH_MOB, summoned->GetGUID());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
void SummonedCreatureDespawn(Creature* summoned) override
|
||||||
|
{
|
||||||
|
if (summoned)
|
||||||
{
|
{
|
||||||
if (pInstance)
|
BossAI::SummonedCreatureDespawn(summoned);
|
||||||
{
|
if (summoned->IsAIEnabled)
|
||||||
pInstance->SetData(DATA_ACHIEV, 0);
|
summoned->AI()->DoAction(-1337);
|
||||||
if (Creature* c = pInstance->instance->GetCreature(SummonedGUID))
|
instance->SetGuidData(DATA_DELETE_TRASH_MOB, summoned->GetGUID());
|
||||||
c->DespawnOrUnsummon();
|
|
||||||
}
|
|
||||||
me->DespawnOrUnsummon(5s);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SummonedCreatureDespawn(Creature* pSummoned) override
|
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||||
{
|
|
||||||
if (pSummoned)
|
|
||||||
pInstance->SetGuidData(DATA_DELETE_TRASH_MOB, pSummoned->GetGUID());
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
void EnterEvadeMode(EvadeReason why) override
|
||||||
|
{
|
||||||
|
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
|
_EnterEvadeMode(why);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct npc_vh_void_sentry : public NullCreatureAI
|
||||||
|
{
|
||||||
|
npc_vh_void_sentry(Creature* c) : NullCreatureAI(c)
|
||||||
|
{
|
||||||
|
_instance = c->GetInstanceScript();
|
||||||
|
_summonedGuid.Clear();
|
||||||
|
_events.ScheduleEvent(EVENT_CHECK_SUMMONER, 5s);
|
||||||
|
if (Creature* summoned = me->SummonCreature(NPC_VOID_SENTRY_BALL, *me, TEMPSUMMON_TIMED_DESPAWN, 300000))
|
||||||
{
|
{
|
||||||
if (checkTimer <= diff)
|
summoned->SetPhaseMask(1, true);
|
||||||
{
|
_summonedGuid = summoned->GetGUID();
|
||||||
checkTimer = 5000;
|
_instance->SetGuidData(DATA_ADD_TRASH_MOB, summoned->GetGUID());
|
||||||
bool good = false;
|
|
||||||
if (me->IsSummon())
|
|
||||||
if (Unit* s = me->ToTempSummon()->GetSummonerUnit())
|
|
||||||
if (s->IsAlive())
|
|
||||||
good = true;
|
|
||||||
if (!good)
|
|
||||||
me->KillSelf();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
checkTimer -= diff;
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
void DoAction(int32 action) override
|
||||||
|
{
|
||||||
|
if (action == -1337)
|
||||||
|
if (Creature* voidSentry = _instance->instance->GetCreature(_summonedGuid))
|
||||||
|
voidSentry->DespawnOrUnsummon();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JustDied(Unit* /*killer*/) override
|
||||||
|
{
|
||||||
|
_instance->SetData(DATA_ACHIEV, 0);
|
||||||
|
if (Creature* voidSentry = _instance->instance->GetCreature(_summonedGuid))
|
||||||
|
voidSentry->DespawnOrUnsummon();
|
||||||
|
me->DespawnOrUnsummon(5s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SummonedCreatureDespawn(Creature* summoned) override
|
||||||
|
{
|
||||||
|
if (summoned)
|
||||||
|
_instance->SetGuidData(DATA_DELETE_TRASH_MOB, summoned->GetGUID());
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
_events.Update(diff);
|
||||||
|
|
||||||
|
if (_events.ExecuteEvent() == EVENT_CHECK_SUMMONER)
|
||||||
|
{
|
||||||
|
bool good = false;
|
||||||
|
if (me->IsSummon())
|
||||||
|
if (Unit* s = me->ToTempSummon()->GetSummonerUnit())
|
||||||
|
if (s->IsAlive())
|
||||||
|
good = true;
|
||||||
|
if (!good)
|
||||||
|
me->KillSelf();
|
||||||
|
_events.Repeat(5s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
InstanceScript* _instance;
|
||||||
|
ObjectGuid _summonedGuid;
|
||||||
|
EventMap _events;
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_zuramat()
|
void AddSC_boss_zuramat()
|
||||||
{
|
{
|
||||||
new boss_zuramat();
|
RegisterVioletHoldCreatureAI(boss_zuramat);
|
||||||
new npc_vh_void_sentry();
|
RegisterVioletHoldCreatureAI(npc_vh_void_sentry);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#include "WorldStateDefines.h"
|
#include "WorldStateDefines.h"
|
||||||
#include "violet_hold.h"
|
#include "violet_hold.h"
|
||||||
|
|
||||||
enum vYells
|
enum VHYells
|
||||||
{
|
{
|
||||||
CYANIGOSA_SAY_SPAWN = 3,
|
CYANIGOSA_SAY_SPAWN = 3,
|
||||||
SAY_SINCLARI_LEAVING = 0,
|
SAY_SINCLARI_LEAVING = 0,
|
||||||
@@ -30,175 +30,163 @@ enum vYells
|
|||||||
SAY_SINCLARI_COMPLETE = 2,
|
SAY_SINCLARI_COMPLETE = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ObjectData const creatureData[] =
|
||||||
|
{
|
||||||
|
{ NPC_MORAGG, BOSS_MORAGG },
|
||||||
|
{ NPC_EREKEM, BOSS_EREKEM },
|
||||||
|
{ NPC_ICHORON, BOSS_ICHORON },
|
||||||
|
{ NPC_LAVANTHOR, BOSS_LAVANTHOR },
|
||||||
|
{ NPC_XEVOZZ, BOSS_XEVOZZ },
|
||||||
|
{ NPC_ZURAMAT, BOSS_ZURAMAT },
|
||||||
|
{ NPC_CYANIGOSA, DATA_CYANIGOSA },
|
||||||
|
{ NPC_SINCLARI, DATA_SINCLARI },
|
||||||
|
{ NPC_PRISON_DOOR_SEAL, DATA_DOOR_SEAL },
|
||||||
|
{ NPC_TELEPORTATION_PORTAL, DATA_TELEPORTATION_PORTAL },
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
ObjectData const goData[] =
|
||||||
|
{
|
||||||
|
{ GO_MAIN_DOOR, DATA_MAIN_DOOR },
|
||||||
|
{ GO_MORAGG_DOOR, DATA_MORAGG_CELL },
|
||||||
|
{ GO_EREKEM_DOOR, DATA_EREKEM_CELL },
|
||||||
|
{ GO_EREKEM_GUARD_1_DOOR, DATA_EREKEM_GUARD_1_CELL },
|
||||||
|
{ GO_EREKEM_GUARD_2_DOOR, DATA_EREKEM_GUARD_2_CELL },
|
||||||
|
{ GO_ICHORON_DOOR, DATA_ICHORON_CELL },
|
||||||
|
{ GO_LAVANTHOR_DOOR, DATA_LAVANTHOR_CELL },
|
||||||
|
{ GO_XEVOZZ_DOOR, DATA_XEVOZZ_CELL },
|
||||||
|
{ GO_ZURAMAT_DOOR, DATA_ZURAMAT_CELL },
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
class instance_violet_hold : public InstanceMapScript
|
class instance_violet_hold : public InstanceMapScript
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
instance_violet_hold() : InstanceMapScript("instance_violet_hold", MAP_VIOLET_HOLD) { }
|
instance_violet_hold() : InstanceMapScript("instance_violet_hold", MAP_VIOLET_HOLD) { }
|
||||||
|
|
||||||
InstanceScript* GetInstanceScript(InstanceMap* pMap) const override
|
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||||
{
|
{
|
||||||
return new instance_violet_hold_InstanceMapScript(pMap);
|
return new instance_violet_hold_InstanceMapScript(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct instance_violet_hold_InstanceMapScript : public InstanceScript
|
struct instance_violet_hold_InstanceMapScript : public InstanceScript
|
||||||
{
|
{
|
||||||
instance_violet_hold_InstanceMapScript(Map* pMap) : InstanceScript(pMap) {}
|
instance_violet_hold_InstanceMapScript(Map* map) : InstanceScript(map)
|
||||||
|
{
|
||||||
uint32 m_auiEncounter[MAX_ENCOUNTER];
|
SetHeaders(DataHeader);
|
||||||
bool CLEANED;
|
SetBossNumber(MAX_BOSS);
|
||||||
uint8 EncounterStatus;
|
SetPersistentDataCount(PERSISTENT_DATA_COUNT);
|
||||||
uint32 uiFirstBoss, uiSecondBoss;
|
LoadObjectData(creatureData, goData);
|
||||||
std::string str_data;
|
}
|
||||||
EventMap events;
|
|
||||||
uint8 GateHealth;
|
|
||||||
uint8 WaveCount;
|
|
||||||
uint8 PortalLocation;
|
|
||||||
bool bAchiev;
|
|
||||||
bool bDefensesUsed;
|
|
||||||
|
|
||||||
GuidVector GO_ActivationCrystalGUID;
|
|
||||||
ObjectGuid GO_MainGateGUID;
|
|
||||||
|
|
||||||
ObjectGuid GO_MoraggCellGUID;
|
|
||||||
ObjectGuid GO_ErekemCellGUID;
|
|
||||||
ObjectGuid GO_ErekemRightGuardCellGUID;
|
|
||||||
ObjectGuid GO_ErekemLeftGuardCellGUID;
|
|
||||||
ObjectGuid GO_IchoronCellGUID;
|
|
||||||
ObjectGuid GO_LavanthorCellGUID;
|
|
||||||
ObjectGuid GO_XevozzCellGUID;
|
|
||||||
ObjectGuid GO_ZuramatCellGUID;
|
|
||||||
|
|
||||||
GuidSet trashMobs;
|
|
||||||
ObjectGuid NPC_SinclariGUID;
|
|
||||||
ObjectGuid NPC_GuardGUID[4];
|
|
||||||
ObjectGuid NPC_PortalGUID;
|
|
||||||
ObjectGuid NPC_DoorSealGUID;
|
|
||||||
|
|
||||||
ObjectGuid NPC_MoraggGUID;
|
|
||||||
ObjectGuid NPC_ErekemGUID;
|
|
||||||
ObjectGuid NPC_ErekemGuardGUID[2];
|
|
||||||
ObjectGuid NPC_IchoronGUID;
|
|
||||||
ObjectGuid NPC_LavanthorGUID;
|
|
||||||
ObjectGuid NPC_XevozzGUID;
|
|
||||||
ObjectGuid NPC_ZuramatGUID;
|
|
||||||
ObjectGuid NPC_CyanigosaGUID;
|
|
||||||
|
|
||||||
void Initialize() override
|
void Initialize() override
|
||||||
{
|
{
|
||||||
SetHeaders(DataHeader);
|
_cleaned = false;
|
||||||
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
|
_encounterStatus = NOT_STARTED;
|
||||||
CLEANED = false;
|
_events.Reset();
|
||||||
EncounterStatus = NOT_STARTED;
|
_events.RescheduleEvent(EVENT_CHECK_PLAYERS, 0ms);
|
||||||
uiFirstBoss = 0;
|
_gateHealth = 100;
|
||||||
uiSecondBoss = 0;
|
_waveCount = 0;
|
||||||
events.Reset();
|
_portalLocation = 0;
|
||||||
events.RescheduleEvent(EVENT_CHECK_PLAYERS, 0ms);
|
_defensesUsed = false;
|
||||||
GateHealth = 100;
|
|
||||||
WaveCount = 0;
|
|
||||||
PortalLocation = 0;
|
|
||||||
bDefensesUsed = false;
|
|
||||||
|
|
||||||
GO_ActivationCrystalGUID.clear();
|
_activationCrystalGuidList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsEncounterInProgress() const override
|
bool IsEncounterInProgress() const override
|
||||||
{
|
{
|
||||||
return false;
|
return _encounterStatus == IN_PROGRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnCreatureCreate(Creature* creature) override
|
void OnCreatureCreate(Creature* creature) override
|
||||||
{
|
{
|
||||||
|
InstanceScript::OnCreatureCreate(creature);
|
||||||
|
|
||||||
switch (creature->GetEntry())
|
switch (creature->GetEntry())
|
||||||
{
|
{
|
||||||
case NPC_SINCLARI:
|
|
||||||
NPC_SinclariGUID = creature->GetGUID();
|
|
||||||
break;
|
|
||||||
case NPC_VIOLET_HOLD_GUARD:
|
case NPC_VIOLET_HOLD_GUARD:
|
||||||
for (uint8 i = 0; i < 4; ++i)
|
for (ObjectGuid& guid : _guardGuid)
|
||||||
if (!NPC_GuardGUID[i])
|
if (!guid)
|
||||||
{
|
{
|
||||||
NPC_GuardGUID[i] = creature->GetGUID();
|
guid = creature->GetGUID();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NPC_DEFENSE_DUMMY_TARGET:
|
case NPC_DEFENSE_DUMMY_TARGET:
|
||||||
creature->ApplySpellImmune(0, IMMUNITY_ID, SPELL_ARCANE_LIGHTNING, true);
|
creature->ApplySpellImmune(0, IMMUNITY_ID, SPELL_ARCANE_LIGHTNING, true);
|
||||||
break;
|
break;
|
||||||
case NPC_TELEPORTATION_PORTAL:
|
|
||||||
NPC_PortalGUID = creature->GetGUID();
|
|
||||||
break;
|
|
||||||
case NPC_PRISON_DOOR_SEAL:
|
|
||||||
NPC_DoorSealGUID = creature->GetGUID();
|
|
||||||
break;
|
|
||||||
// BOSSES BELOW:
|
|
||||||
case NPC_XEVOZZ:
|
|
||||||
NPC_XevozzGUID = creature->GetGUID();
|
|
||||||
break;
|
|
||||||
case NPC_LAVANTHOR:
|
|
||||||
NPC_LavanthorGUID = creature->GetGUID();
|
|
||||||
break;
|
|
||||||
case NPC_ICHORON:
|
|
||||||
NPC_IchoronGUID = creature->GetGUID();
|
|
||||||
break;
|
|
||||||
case NPC_ZURAMAT:
|
|
||||||
NPC_ZuramatGUID = creature->GetGUID();
|
|
||||||
break;
|
|
||||||
case NPC_EREKEM:
|
|
||||||
NPC_ErekemGUID = creature->GetGUID();
|
|
||||||
break;
|
|
||||||
case NPC_EREKEM_GUARD:
|
case NPC_EREKEM_GUARD:
|
||||||
if (!NPC_ErekemGuardGUID[0])
|
if (!_erekemGuardGuid[0])
|
||||||
NPC_ErekemGuardGUID[0] = creature->GetGUID();
|
_erekemGuardGuid[0] = creature->GetGUID();
|
||||||
else
|
else
|
||||||
NPC_ErekemGuardGUID[1] = creature->GetGUID();
|
_erekemGuardGuid[1] = creature->GetGUID();
|
||||||
break;
|
|
||||||
case NPC_MORAGG:
|
|
||||||
NPC_MoraggGUID = creature->GetGUID();
|
|
||||||
break;
|
|
||||||
case NPC_CYANIGOSA:
|
|
||||||
NPC_CyanigosaGUID = creature->GetGUID();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnGameObjectCreate(GameObject* go) override
|
void OnGameObjectCreate(GameObject* go) override
|
||||||
{
|
{
|
||||||
switch (go->GetEntry())
|
InstanceScript::OnGameObjectCreate(go);
|
||||||
|
|
||||||
|
if (go->GetEntry() == GO_ACTIVATION_CRYSTAL)
|
||||||
{
|
{
|
||||||
case GO_ACTIVATION_CRYSTAL:
|
HandleGameObject(ObjectGuid::Empty, false, go);
|
||||||
HandleGameObject(ObjectGuid::Empty, false, go); // make go not used yet
|
go->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||||
go->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE); // not useable at the beginning
|
_activationCrystalGuidList.push_back(go->GetGUID());
|
||||||
GO_ActivationCrystalGUID.push_back(go->GetGUID());
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetBossState(uint32 id, EncounterState state) override
|
||||||
|
{
|
||||||
|
if (!InstanceScript::SetBossState(id, state))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case BOSS_MORAGG:
|
||||||
|
case BOSS_EREKEM:
|
||||||
|
case BOSS_ICHORON:
|
||||||
|
case BOSS_LAVANTHOR:
|
||||||
|
case BOSS_XEVOZZ:
|
||||||
|
case BOSS_ZURAMAT:
|
||||||
|
if (state == DONE)
|
||||||
|
{
|
||||||
|
if (_waveCount == 6)
|
||||||
|
SetBossState(DATA_1ST_BOSS, DONE);
|
||||||
|
else if (_waveCount == 12)
|
||||||
|
SetBossState(DATA_2ND_BOSS, DONE);
|
||||||
|
_events.RescheduleEvent(EVENT_SUMMON_PORTAL, 35s);
|
||||||
|
}
|
||||||
|
else if (state == FAIL || state == NOT_STARTED)
|
||||||
|
{
|
||||||
|
_cleaned = false;
|
||||||
|
InstanceCleanup();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GO_MAIN_DOOR:
|
case DATA_CYANIGOSA:
|
||||||
GO_MainGateGUID = go->GetGUID();
|
if (state == DONE)
|
||||||
|
{
|
||||||
|
_encounterStatus = DONE;
|
||||||
|
HandleGameObject(DATA_MAIN_DOOR, true);
|
||||||
|
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_SHOW, 0);
|
||||||
|
if (Creature* sinclari = GetCreature(DATA_SINCLARI))
|
||||||
|
{
|
||||||
|
sinclari->AI()->Talk(SAY_SINCLARI_COMPLETE);
|
||||||
|
sinclari->DespawnOrUnsummon();
|
||||||
|
sinclari->SetRespawnTime(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (state == FAIL || state == NOT_STARTED)
|
||||||
|
{
|
||||||
|
_cleaned = false;
|
||||||
|
InstanceCleanup();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
// BOSS GATES BELOW:
|
default:
|
||||||
case GO_EREKEM_GUARD_1_DOOR:
|
|
||||||
GO_ErekemLeftGuardCellGUID = go->GetGUID();
|
|
||||||
break;
|
|
||||||
case GO_EREKEM_GUARD_2_DOOR:
|
|
||||||
GO_ErekemRightGuardCellGUID = go->GetGUID();
|
|
||||||
break;
|
|
||||||
case GO_EREKEM_DOOR:
|
|
||||||
GO_ErekemCellGUID = go->GetGUID();
|
|
||||||
break;
|
|
||||||
case GO_ZURAMAT_DOOR:
|
|
||||||
GO_ZuramatCellGUID = go->GetGUID();
|
|
||||||
break;
|
|
||||||
case GO_LAVANTHOR_DOOR:
|
|
||||||
GO_LavanthorCellGUID = go->GetGUID();
|
|
||||||
break;
|
|
||||||
case GO_MORAGG_DOOR:
|
|
||||||
GO_MoraggCellGUID = go->GetGUID();
|
|
||||||
break;
|
|
||||||
case GO_ICHORON_DOOR:
|
|
||||||
GO_IchoronCellGUID = go->GetGUID();
|
|
||||||
break;
|
|
||||||
case GO_XEVOZZ_DOOR:
|
|
||||||
GO_XevozzCellGUID = go->GetGUID();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetData(uint32 type, uint32 data) override
|
void SetData(uint32 type, uint32 data) override
|
||||||
@@ -208,90 +196,57 @@ public:
|
|||||||
case DATA_ACTIVATE_DEFENSE_SYSTEM:
|
case DATA_ACTIVATE_DEFENSE_SYSTEM:
|
||||||
{
|
{
|
||||||
if (data)
|
if (data)
|
||||||
bDefensesUsed = true;
|
_defensesUsed = true;
|
||||||
const Position pos = {1919.09546f, 812.29724f, 86.2905f, M_PI};
|
Position const pos = {1919.09546f, 812.29724f, 86.2905f, M_PI};
|
||||||
instance->SummonCreature(NPC_DEFENSE_SYSTEM, pos, 0, 6499);
|
instance->SummonCreature(NPC_DEFENSE_SYSTEM, pos, 0, 6499);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DATA_START_INSTANCE:
|
case DATA_START_INSTANCE:
|
||||||
if (EncounterStatus == NOT_STARTED)
|
if (_encounterStatus == NOT_STARTED)
|
||||||
{
|
{
|
||||||
EncounterStatus = IN_PROGRESS;
|
_encounterStatus = IN_PROGRESS;
|
||||||
if (Creature* c = instance->GetCreature(NPC_SinclariGUID))
|
if (Creature* sinclari = GetCreature(DATA_SINCLARI))
|
||||||
{
|
{
|
||||||
c->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
sinclari->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||||
c->AI()->Talk(SAY_SINCLARI_LEAVING);
|
sinclari->AI()->Talk(SAY_SINCLARI_LEAVING);
|
||||||
/// @todo: Missing orientation for Sinclari's movement and "interaction" animation with the nearby crystal.
|
|
||||||
}
|
}
|
||||||
events.RescheduleEvent(EVENT_GUARDS_FALL_BACK, 4s);
|
_events.RescheduleEvent(EVENT_GUARDS_FALL_BACK, 4s);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DATA_PORTAL_DEFEATED:
|
case DATA_PORTAL_DEFEATED:
|
||||||
events.RescheduleEvent(EVENT_SUMMON_PORTAL, 3s);
|
_events.RescheduleEvent(EVENT_SUMMON_PORTAL, 3s);
|
||||||
break;
|
break;
|
||||||
case DATA_PORTAL_LOCATION:
|
case DATA_PORTAL_LOCATION:
|
||||||
PortalLocation = data;
|
_portalLocation = data;
|
||||||
break;
|
break;
|
||||||
case DATA_DECRASE_DOOR_HEALTH:
|
case DATA_DECREASE_DOOR_HEALTH:
|
||||||
if (GateHealth > 0)
|
if (_gateHealth > 0)
|
||||||
--GateHealth;
|
--_gateHealth;
|
||||||
if (GateHealth == 0)
|
if (_gateHealth == 0)
|
||||||
{
|
{
|
||||||
CLEANED = false;
|
_cleaned = false;
|
||||||
InstanceCleanup();
|
InstanceCleanup();
|
||||||
}
|
}
|
||||||
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_PRISON_STATE, (uint32)GateHealth);
|
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_PRISON_STATE, (uint32)_gateHealth);
|
||||||
break;
|
break;
|
||||||
case DATA_RELEASE_BOSS:
|
case DATA_RELEASE_BOSS:
|
||||||
if (WaveCount == 6)
|
if (_waveCount == 6)
|
||||||
StartBossEncounter(uiFirstBoss);
|
StartBossEncounter(GetPersistentData(PERSISTENT_DATA_FIRST_BOSS));
|
||||||
else
|
else
|
||||||
StartBossEncounter(uiSecondBoss);
|
StartBossEncounter(GetPersistentData(PERSISTENT_DATA_SECOND_BOSS));
|
||||||
break;
|
|
||||||
case DATA_BOSS_DIED:
|
|
||||||
if (WaveCount == 6)
|
|
||||||
m_auiEncounter[0] = DONE;
|
|
||||||
else if (WaveCount == 12)
|
|
||||||
m_auiEncounter[1] = DONE;
|
|
||||||
else if (WaveCount == 18)
|
|
||||||
{
|
|
||||||
m_auiEncounter[2] = DONE;
|
|
||||||
EncounterStatus = DONE;
|
|
||||||
HandleGameObject(GO_MainGateGUID, true);
|
|
||||||
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_SHOW, 0);
|
|
||||||
if (Creature* c = instance->GetCreature(NPC_SinclariGUID))
|
|
||||||
{
|
|
||||||
c->AI()->Talk(SAY_SINCLARI_COMPLETE);
|
|
||||||
c->DespawnOrUnsummon();
|
|
||||||
c->SetRespawnTime(3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SaveToDB();
|
|
||||||
if (WaveCount < 18)
|
|
||||||
events.RescheduleEvent(EVENT_SUMMON_PORTAL, 35s);
|
|
||||||
break;
|
|
||||||
case DATA_FAILED:
|
|
||||||
CLEANED = false;
|
|
||||||
InstanceCleanup();
|
|
||||||
break;
|
break;
|
||||||
case DATA_ACHIEV:
|
case DATA_ACHIEV:
|
||||||
bAchiev = !!data;
|
_achievementCompleted = !!data;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetGuidData(uint32 type, ObjectGuid data) override
|
void SetGuidData(uint32 type, ObjectGuid data) override
|
||||||
{
|
{
|
||||||
switch (type)
|
if (type == DATA_ADD_TRASH_MOB)
|
||||||
{
|
_trashMobs.insert(data);
|
||||||
case DATA_ADD_TRASH_MOB:
|
else if (type == DATA_DELETE_TRASH_MOB && !_cleaned)
|
||||||
trashMobs.insert(data);
|
_trashMobs.erase(data);
|
||||||
break;
|
|
||||||
case DATA_DELETE_TRASH_MOB:
|
|
||||||
if (!CLEANED)
|
|
||||||
trashMobs.erase(data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 GetData(uint32 type) const override
|
uint32 GetData(uint32 type) const override
|
||||||
@@ -299,15 +254,11 @@ public:
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case DATA_ENCOUNTER_STATUS:
|
case DATA_ENCOUNTER_STATUS:
|
||||||
return (uint32)EncounterStatus;
|
return (uint32)_encounterStatus;
|
||||||
case DATA_WAVE_COUNT:
|
case DATA_WAVE_COUNT:
|
||||||
return (uint32)WaveCount;
|
return (uint32)_waveCount;
|
||||||
case DATA_PORTAL_LOCATION:
|
case DATA_PORTAL_LOCATION:
|
||||||
return PortalLocation;
|
return _portalLocation;
|
||||||
case DATA_FIRST_BOSS_NUMBER:
|
|
||||||
return uiFirstBoss;
|
|
||||||
case DATA_SECOND_BOSS_NUMBER:
|
|
||||||
return uiSecondBoss;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -315,212 +266,180 @@ public:
|
|||||||
|
|
||||||
ObjectGuid GetGuidData(uint32 identifier) const override
|
ObjectGuid GetGuidData(uint32 identifier) const override
|
||||||
{
|
{
|
||||||
switch (identifier)
|
if (identifier == DATA_EREKEM_GUARD_1_GUID)
|
||||||
{
|
return _erekemGuardGuid[0];
|
||||||
case DATA_TELEPORTATION_PORTAL_GUID:
|
if (identifier == DATA_EREKEM_GUARD_2_GUID)
|
||||||
return NPC_PortalGUID;
|
return _erekemGuardGuid[1];
|
||||||
case DATA_DOOR_SEAL_GUID:
|
|
||||||
return NPC_DoorSealGUID;
|
|
||||||
case DATA_EREKEM_GUID:
|
|
||||||
return NPC_ErekemGUID;
|
|
||||||
case DATA_EREKEM_GUARD_1_GUID:
|
|
||||||
return NPC_ErekemGuardGUID[0];
|
|
||||||
case DATA_EREKEM_GUARD_2_GUID:
|
|
||||||
return NPC_ErekemGuardGUID[1];
|
|
||||||
case DATA_ICHORON_GUID:
|
|
||||||
return NPC_IchoronGUID;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ObjectGuid::Empty;
|
return ObjectGuid::Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartBossEncounter(uint8 uiBoss)
|
void StartBossEncounter(uint32 bossId)
|
||||||
{
|
{
|
||||||
Creature* pBoss = nullptr;
|
switch (bossId)
|
||||||
|
|
||||||
switch (uiBoss)
|
|
||||||
{
|
{
|
||||||
case BOSS_MORAGG:
|
case BOSS_MORAGG:
|
||||||
HandleGameObject(GO_MoraggCellGUID, true);
|
HandleGameObject(DATA_MORAGG_CELL, true);
|
||||||
pBoss = instance->GetCreature(NPC_MoraggGUID);
|
|
||||||
if (pBoss)
|
|
||||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove1);
|
|
||||||
break;
|
break;
|
||||||
case BOSS_EREKEM:
|
case BOSS_EREKEM:
|
||||||
HandleGameObject(GO_ErekemCellGUID, true);
|
HandleGameObject(DATA_EREKEM_CELL, true);
|
||||||
HandleGameObject(GO_ErekemRightGuardCellGUID, true);
|
HandleGameObject(DATA_EREKEM_GUARD_2_CELL, true);
|
||||||
HandleGameObject(GO_ErekemLeftGuardCellGUID, true);
|
HandleGameObject(DATA_EREKEM_GUARD_1_CELL, true);
|
||||||
pBoss = instance->GetCreature(NPC_ErekemGUID);
|
if (Creature* guard1 = instance->GetCreature(_erekemGuardGuid[0]))
|
||||||
if (pBoss)
|
|
||||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove2);
|
|
||||||
if (Creature* pGuard1 = instance->GetCreature(NPC_ErekemGuardGUID[0]))
|
|
||||||
{
|
{
|
||||||
pGuard1->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
guard1->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||||
pGuard1->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
guard1->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
pGuard1->SetImmuneToNPC(false);
|
guard1->SetImmuneToNPC(false);
|
||||||
pGuard1->GetMotionMaster()->MovePoint(0, BossStartMove21);
|
guard1->GetMotionMaster()->MovePoint(0, BossStartMove21);
|
||||||
}
|
}
|
||||||
if (Creature* pGuard2 = instance->GetCreature(NPC_ErekemGuardGUID[1]))
|
if (Creature* guard2 = instance->GetCreature(_erekemGuardGuid[1]))
|
||||||
{
|
{
|
||||||
pGuard2->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
guard2->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||||
pGuard2->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
guard2->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
pGuard2->SetImmuneToNPC(false);
|
guard2->SetImmuneToNPC(false);
|
||||||
pGuard2->GetMotionMaster()->MovePoint(0, BossStartMove22);
|
guard2->GetMotionMaster()->MovePoint(0, BossStartMove22);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BOSS_ICHORON:
|
case BOSS_ICHORON:
|
||||||
HandleGameObject(GO_IchoronCellGUID, true);
|
HandleGameObject(DATA_ICHORON_CELL, true);
|
||||||
pBoss = instance->GetCreature(NPC_IchoronGUID);
|
|
||||||
if (pBoss)
|
|
||||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove3);
|
|
||||||
break;
|
break;
|
||||||
case BOSS_LAVANTHOR:
|
case BOSS_LAVANTHOR:
|
||||||
HandleGameObject(GO_LavanthorCellGUID, true);
|
HandleGameObject(DATA_LAVANTHOR_CELL, true);
|
||||||
pBoss = instance->GetCreature(NPC_LavanthorGUID);
|
|
||||||
if (pBoss)
|
|
||||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove4);
|
|
||||||
break;
|
break;
|
||||||
case BOSS_XEVOZZ:
|
case BOSS_XEVOZZ:
|
||||||
HandleGameObject(GO_XevozzCellGUID, true);
|
HandleGameObject(DATA_XEVOZZ_CELL, true);
|
||||||
pBoss = instance->GetCreature(NPC_XevozzGUID);
|
|
||||||
if (pBoss)
|
|
||||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove5);
|
|
||||||
break;
|
break;
|
||||||
case BOSS_ZURAMAT:
|
case BOSS_ZURAMAT:
|
||||||
HandleGameObject(GO_ZuramatCellGUID, true);
|
HandleGameObject(DATA_ZURAMAT_CELL, true);
|
||||||
pBoss = instance->GetCreature(NPC_ZuramatGUID);
|
|
||||||
if (pBoss)
|
|
||||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove6);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pBoss)
|
static Position const BossStartPositions[] =
|
||||||
{
|
{
|
||||||
pBoss->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
BossStartMove1, // BOSS_MORAGG
|
||||||
pBoss->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
BossStartMove2, // BOSS_EREKEM
|
||||||
pBoss->SetImmuneToNPC(false);
|
BossStartMove3, // BOSS_ICHORON
|
||||||
pBoss->SetReactState(REACT_AGGRESSIVE);
|
BossStartMove4, // BOSS_LAVANTHOR
|
||||||
if ((WaveCount == 6 && m_auiEncounter[0] == DONE) || (WaveCount == 12 && m_auiEncounter[1] == DONE))
|
BossStartMove5, // BOSS_XEVOZZ
|
||||||
pBoss->SetLootMode(0);
|
BossStartMove6, // BOSS_ZURAMAT
|
||||||
|
};
|
||||||
|
|
||||||
|
Creature* boss = GetCreature(bossId);
|
||||||
|
if (boss)
|
||||||
|
{
|
||||||
|
boss->GetMotionMaster()->MovePoint(0, BossStartPositions[bossId - BOSS_MORAGG]);
|
||||||
|
boss->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||||
|
boss->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
|
boss->SetImmuneToNPC(false);
|
||||||
|
boss->SetReactState(REACT_AGGRESSIVE);
|
||||||
|
if ((_waveCount == 6 && GetBossState(DATA_1ST_BOSS) == DONE) || (_waveCount == 12 && GetBossState(DATA_2ND_BOSS) == DONE))
|
||||||
|
boss->SetLootMode(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update(uint32 diff) override
|
void Update(uint32 diff) override
|
||||||
{
|
{
|
||||||
events.Update(diff);
|
_events.Update(diff);
|
||||||
switch (events.ExecuteEvent())
|
switch (_events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case EVENT_CHECK_PLAYERS:
|
case EVENT_CHECK_PLAYERS:
|
||||||
{
|
if (DoNeedCleanup(false))
|
||||||
if (DoNeedCleanup(false))
|
InstanceCleanup();
|
||||||
InstanceCleanup();
|
_events.Repeat(5s);
|
||||||
events.Repeat(5s);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case EVENT_GUARDS_FALL_BACK:
|
case EVENT_GUARDS_FALL_BACK:
|
||||||
{
|
for (ObjectGuid const& guid : _guardGuid)
|
||||||
for (uint8 i = 0; i < 4; ++i)
|
if (Creature* guard = instance->GetCreature(guid))
|
||||||
if (Creature* c = instance->GetCreature(NPC_GuardGUID[i]))
|
{
|
||||||
{
|
guard->SetReactState(REACT_PASSIVE);
|
||||||
c->SetReactState(REACT_PASSIVE);
|
guard->CombatStop();
|
||||||
c->CombatStop();
|
guard->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||||
c->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
guard->GetMotionMaster()->MovePoint(0, guardMovePosition);
|
||||||
c->GetMotionMaster()->MovePoint(0, guardMovePosition);
|
}
|
||||||
}
|
_events.RescheduleEvent(EVENT_GUARDS_DISAPPEAR, 5s);
|
||||||
events.RescheduleEvent(EVENT_GUARDS_DISAPPEAR, 5s);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case EVENT_GUARDS_DISAPPEAR:
|
case EVENT_GUARDS_DISAPPEAR:
|
||||||
{
|
for (ObjectGuid const& guid : _guardGuid)
|
||||||
for (uint8 i = 0; i < 4; ++i)
|
if (Creature* guard = instance->GetCreature(guid))
|
||||||
if (Creature* c = instance->GetCreature(NPC_GuardGUID[i]))
|
guard->SetVisible(false);
|
||||||
c->SetVisible(false);
|
_events.RescheduleEvent(EVENT_SINCLARI_FALL_BACK, 2s);
|
||||||
events.RescheduleEvent(EVENT_SINCLARI_FALL_BACK, 2s);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case EVENT_SINCLARI_FALL_BACK:
|
case EVENT_SINCLARI_FALL_BACK:
|
||||||
|
if (Creature* sinclari = GetCreature(DATA_SINCLARI))
|
||||||
{
|
{
|
||||||
if (Creature* c = instance->GetCreature(NPC_SinclariGUID))
|
sinclari->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||||
{
|
sinclari->GetMotionMaster()->MovePoint(0, sinclariOutsidePosition);
|
||||||
c->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
|
||||||
c->GetMotionMaster()->MovePoint(0, sinclariOutsidePosition);
|
|
||||||
}
|
|
||||||
SetData(DATA_ACTIVATE_DEFENSE_SYSTEM, 0);
|
|
||||||
events.RescheduleEvent(EVENT_START_ENCOUNTER, 4s);
|
|
||||||
}
|
}
|
||||||
|
SetData(DATA_ACTIVATE_DEFENSE_SYSTEM, 0);
|
||||||
|
_events.RescheduleEvent(EVENT_START_ENCOUNTER, 4s);
|
||||||
break;
|
break;
|
||||||
case EVENT_START_ENCOUNTER:
|
case EVENT_START_ENCOUNTER:
|
||||||
|
if (Creature* sinclari = GetCreature(DATA_SINCLARI))
|
||||||
{
|
{
|
||||||
if (Creature* c = instance->GetCreature(NPC_SinclariGUID))
|
sinclari->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||||
{
|
sinclari->AI()->Talk(SAY_SINCLARI_DOOR_LOCK);
|
||||||
c->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
|
||||||
c->AI()->Talk(SAY_SINCLARI_DOOR_LOCK);
|
|
||||||
}
|
|
||||||
if (Creature* c = instance->GetCreature(NPC_DoorSealGUID))
|
|
||||||
{
|
|
||||||
c->RemoveAllAuras(); // just to be sure...
|
|
||||||
}
|
|
||||||
GateHealth = 100;
|
|
||||||
HandleGameObject(GO_MainGateGUID, false);
|
|
||||||
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_SHOW, 1);
|
|
||||||
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_PRISON_STATE, (uint32)GateHealth);
|
|
||||||
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_WAVE_COUNT, (uint32)WaveCount);
|
|
||||||
|
|
||||||
for (ObjectGuid const& guid : GO_ActivationCrystalGUID)
|
|
||||||
if (GameObject* go = instance->GetGameObject(guid))
|
|
||||||
{
|
|
||||||
HandleGameObject(ObjectGuid::Empty, false, go); // not used yet
|
|
||||||
go->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE); // make it useable
|
|
||||||
}
|
|
||||||
events.RescheduleEvent(EVENT_SUMMON_PORTAL, 4s);
|
|
||||||
}
|
}
|
||||||
|
if (Creature* doorSeal = GetCreature(DATA_DOOR_SEAL))
|
||||||
|
doorSeal->RemoveAllAuras();
|
||||||
|
_gateHealth = 100;
|
||||||
|
HandleGameObject(DATA_MAIN_DOOR, false);
|
||||||
|
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_SHOW, 1);
|
||||||
|
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_PRISON_STATE, (uint32)_gateHealth);
|
||||||
|
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_WAVE_COUNT, (uint32)_waveCount);
|
||||||
|
|
||||||
|
for (ObjectGuid const& guid : _activationCrystalGuidList)
|
||||||
|
if (GameObject* go = instance->GetGameObject(guid))
|
||||||
|
{
|
||||||
|
HandleGameObject(ObjectGuid::Empty, false, go);
|
||||||
|
go->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||||
|
}
|
||||||
|
_events.RescheduleEvent(EVENT_SUMMON_PORTAL, 4s);
|
||||||
break;
|
break;
|
||||||
case EVENT_SUMMON_PORTAL:
|
case EVENT_SUMMON_PORTAL:
|
||||||
++WaveCount;
|
++_waveCount;
|
||||||
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_WAVE_COUNT, (uint32)WaveCount);
|
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_WAVE_COUNT, (uint32)_waveCount);
|
||||||
SetData(DATA_PORTAL_LOCATION, (GetData(DATA_PORTAL_LOCATION) + urand(1, 5)) % 6);
|
SetData(DATA_PORTAL_LOCATION, (GetData(DATA_PORTAL_LOCATION) + urand(1, 5)) % 6);
|
||||||
if (Creature* c = instance->GetCreature(NPC_SinclariGUID))
|
if (Creature* sinclari = GetCreature(DATA_SINCLARI))
|
||||||
{
|
{
|
||||||
if (WaveCount % 6 != 0)
|
if (_waveCount % 6 != 0)
|
||||||
c->SummonCreature(NPC_TELEPORTATION_PORTAL, PortalLocations[GetData(DATA_PORTAL_LOCATION)], TEMPSUMMON_CORPSE_DESPAWN);
|
sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, PortalLocations[GetData(DATA_PORTAL_LOCATION)], TEMPSUMMON_CORPSE_DESPAWN);
|
||||||
else if (WaveCount == 6 || WaveCount == 12) // first or second boss
|
else if (_waveCount == 6 || _waveCount == 12)
|
||||||
{
|
{
|
||||||
if (!uiFirstBoss || !uiSecondBoss)
|
if (!GetPersistentData(PERSISTENT_DATA_FIRST_BOSS) || !GetPersistentData(PERSISTENT_DATA_SECOND_BOSS))
|
||||||
{
|
{
|
||||||
uiFirstBoss = urand(1, 6);
|
uint32 firstBoss = urand(BOSS_MORAGG, BOSS_ZURAMAT);
|
||||||
do { uiSecondBoss = urand(1, 6); }
|
uint32 secondBoss;
|
||||||
while (uiFirstBoss == uiSecondBoss);
|
do { secondBoss = urand(BOSS_MORAGG, BOSS_ZURAMAT); }
|
||||||
SaveToDB();
|
while (firstBoss == secondBoss);
|
||||||
|
StorePersistentData(PERSISTENT_DATA_FIRST_BOSS, firstBoss);
|
||||||
|
StorePersistentData(PERSISTENT_DATA_SECOND_BOSS, secondBoss);
|
||||||
}
|
}
|
||||||
c->SummonCreature(NPC_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN);
|
sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN);
|
||||||
}
|
}
|
||||||
else // cyanigossa
|
else
|
||||||
{
|
{
|
||||||
if (Creature* cyanigosa = c->SummonCreature(NPC_CYANIGOSA, CyanigosasSpawnLocation, TEMPSUMMON_DEAD_DESPAWN))
|
if (Creature* cyanigosa = sinclari->SummonCreature(NPC_CYANIGOSA, CyanigosasSpawnLocation, TEMPSUMMON_DEAD_DESPAWN))
|
||||||
{
|
{
|
||||||
cyanigosa->CastSpell(cyanigosa, SPELL_CYANIGOSA_BLUE_AURA, false);
|
cyanigosa->CastSpell(cyanigosa, SPELL_CYANIGOSA_BLUE_AURA, false);
|
||||||
cyanigosa->AI()->Talk(CYANIGOSA_SAY_SPAWN);
|
cyanigosa->AI()->Talk(CYANIGOSA_SAY_SPAWN);
|
||||||
cyanigosa->GetMotionMaster()->MoveJump(MiddleRoomLocation.GetPositionX(), MiddleRoomLocation.GetPositionY(), MiddleRoomLocation.GetPositionZ(), 10.0f, 20.0f);
|
cyanigosa->GetMotionMaster()->MoveJump(MiddleRoomLocation.GetPositionX(), MiddleRoomLocation.GetPositionY(), MiddleRoomLocation.GetPositionZ(), 10.0f, 20.0f);
|
||||||
}
|
}
|
||||||
events.RescheduleEvent(EVENT_CYANIGOSSA_TRANSFORM, 10s);
|
_events.RescheduleEvent(EVENT_CYANIGOSA_TRANSFORM, 10s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EVENT_CYANIGOSSA_TRANSFORM:
|
case EVENT_CYANIGOSA_TRANSFORM:
|
||||||
if (Creature* c = instance->GetCreature(NPC_CyanigosaGUID))
|
if (Creature* cyanigosa = GetCreature(DATA_CYANIGOSA))
|
||||||
{
|
{
|
||||||
c->RemoveAurasDueToSpell(SPELL_CYANIGOSA_BLUE_AURA);
|
cyanigosa->RemoveAurasDueToSpell(SPELL_CYANIGOSA_BLUE_AURA);
|
||||||
c->CastSpell(c, SPELL_CYANIGOSA_TRANSFORM, 0);
|
cyanigosa->CastSpell(cyanigosa, SPELL_CYANIGOSA_TRANSFORM, 0);
|
||||||
events.RescheduleEvent(EVENT_CYANIGOSA_ATTACK, 2500ms);
|
_events.RescheduleEvent(EVENT_CYANIGOSA_ATTACK, 2500ms);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EVENT_CYANIGOSA_ATTACK:
|
case EVENT_CYANIGOSA_ATTACK:
|
||||||
if (Creature* c = instance->GetCreature(NPC_CyanigosaGUID))
|
if (Creature* cyanigosa = GetCreature(DATA_CYANIGOSA))
|
||||||
{
|
{
|
||||||
c->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
cyanigosa->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
c->SetImmuneToNPC(false);
|
cyanigosa->SetImmuneToNPC(false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -531,121 +450,118 @@ public:
|
|||||||
if (DoNeedCleanup(plr->IsAlive()))
|
if (DoNeedCleanup(plr->IsAlive()))
|
||||||
InstanceCleanup();
|
InstanceCleanup();
|
||||||
|
|
||||||
if (EncounterStatus == IN_PROGRESS)
|
if (_encounterStatus == IN_PROGRESS)
|
||||||
{
|
{
|
||||||
plr->SendUpdateWorldState(WORLD_STATE_VIOLET_HOLD_SHOW, 1);
|
plr->SendUpdateWorldState(WORLD_STATE_VIOLET_HOLD_SHOW, 1);
|
||||||
plr->SendUpdateWorldState(WORLD_STATE_VIOLET_HOLD_PRISON_STATE, (uint32)GateHealth);
|
plr->SendUpdateWorldState(WORLD_STATE_VIOLET_HOLD_PRISON_STATE, (uint32)_gateHealth);
|
||||||
plr->SendUpdateWorldState(WORLD_STATE_VIOLET_HOLD_WAVE_COUNT, (uint32)WaveCount);
|
plr->SendUpdateWorldState(WORLD_STATE_VIOLET_HOLD_WAVE_COUNT, (uint32)_waveCount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
plr->SendUpdateWorldState(WORLD_STATE_VIOLET_HOLD_SHOW, 0);
|
plr->SendUpdateWorldState(WORLD_STATE_VIOLET_HOLD_SHOW, 0);
|
||||||
|
|
||||||
events.RescheduleEvent(EVENT_CHECK_PLAYERS, 5s);
|
_events.RescheduleEvent(EVENT_CHECK_PLAYERS, 5s);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DoNeedCleanup(bool enter)
|
bool DoNeedCleanup(bool enter)
|
||||||
{
|
{
|
||||||
uint8 aliveCount = 0;
|
uint32 aliveCount = instance->GetPlayersCountExceptGMs(true);
|
||||||
Map::PlayerList const& pl = instance->GetPlayers();
|
|
||||||
for( Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
|
|
||||||
if (Player* plr = itr->GetSource())
|
|
||||||
if (plr->IsAlive() && !plr->IsGameMaster() && !plr->HasAura(27827)/*spirit of redemption aura*/ )
|
|
||||||
++aliveCount;
|
|
||||||
|
|
||||||
bool need = enter ? aliveCount <= 1 : aliveCount == 0;
|
bool need = enter ? aliveCount <= 1 : aliveCount == 0;
|
||||||
if (!need && CLEANED)
|
if (!need && _cleaned)
|
||||||
CLEANED = false;
|
_cleaned = false;
|
||||||
return need;
|
return need;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceCleanup()
|
void InstanceCleanup()
|
||||||
{
|
{
|
||||||
if (CLEANED)
|
if (_cleaned)
|
||||||
return;
|
return;
|
||||||
CLEANED = true;
|
_cleaned = true;
|
||||||
|
|
||||||
// reset defense crystals
|
for (ObjectGuid const& guid : _activationCrystalGuidList)
|
||||||
for (ObjectGuid const& guid : GO_ActivationCrystalGUID)
|
|
||||||
if (GameObject* go = instance->GetGameObject(guid))
|
if (GameObject* go = instance->GetGameObject(guid))
|
||||||
{
|
{
|
||||||
HandleGameObject(ObjectGuid::Empty, false, go); // not used yet
|
HandleGameObject(ObjectGuid::Empty, false, go);
|
||||||
go->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE); // not useable at the beginning
|
go->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset positions of Sinclari and Guards
|
if (Creature* sinclari = GetCreature(DATA_SINCLARI))
|
||||||
if (Creature* c = instance->GetCreature(NPC_SinclariGUID))
|
|
||||||
{
|
{
|
||||||
c->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
sinclari->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||||
c->DespawnOrUnsummon();
|
sinclari->DespawnOrUnsummon();
|
||||||
c->SetRespawnTime(3);
|
sinclari->SetRespawnTime(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8 i = 0; i < 4; ++i)
|
for (ObjectGuid const& guid : _guardGuid)
|
||||||
if (Creature* c = instance->GetCreature(NPC_GuardGUID[i]))
|
if (Creature* guard = instance->GetCreature(guid))
|
||||||
{
|
{
|
||||||
c->DespawnOrUnsummon();
|
guard->DespawnOrUnsummon();
|
||||||
c->SetRespawnTime(3);
|
guard->SetRespawnTime(3);
|
||||||
if (m_auiEncounter[MAX_ENCOUNTER - 1] == DONE)
|
guard->SetVisible(GetBossState(DATA_CYANIGOSA) != DONE);
|
||||||
c->SetVisible(false);
|
guard->SetReactState(REACT_AGGRESSIVE);
|
||||||
else
|
|
||||||
c->SetVisible(true);
|
|
||||||
c->SetReactState(REACT_AGGRESSIVE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove portal if any
|
if (Creature* portal = GetCreature(DATA_TELEPORTATION_PORTAL))
|
||||||
if (Creature* c = instance->GetCreature(NPC_PortalGUID))
|
portal->DespawnOrUnsummon();
|
||||||
c->DespawnOrUnsummon();
|
|
||||||
NPC_PortalGUID.Clear();
|
|
||||||
|
|
||||||
// remove trash
|
for (ObjectGuid const& guid : _trashMobs)
|
||||||
for (ObjectGuid const& guid : trashMobs)
|
if (Creature* trash = instance->GetCreature(guid))
|
||||||
if (Creature* c = instance->GetCreature(guid))
|
trash->DespawnOrUnsummon();
|
||||||
c->DespawnOrUnsummon();
|
|
||||||
|
|
||||||
trashMobs.clear();
|
_trashMobs.clear();
|
||||||
|
|
||||||
// clear door seal damaging auras:
|
if (Creature* doorSeal = GetCreature(DATA_DOOR_SEAL))
|
||||||
if (Creature* c = instance->GetCreature(NPC_DoorSealGUID))
|
doorSeal->RemoveAllAuras();
|
||||||
c->RemoveAllAuras();
|
|
||||||
|
|
||||||
// open main gate
|
HandleGameObject(DATA_MAIN_DOOR, true);
|
||||||
HandleGameObject(GO_MainGateGUID, true);
|
|
||||||
|
|
||||||
if (m_auiEncounter[MAX_ENCOUNTER - 1] != DONE) // instance not finished
|
if (GetBossState(DATA_CYANIGOSA) != DONE)
|
||||||
{
|
{
|
||||||
// close all cells
|
HandleGameObject(DATA_MORAGG_CELL, false);
|
||||||
HandleGameObject(GO_MoraggCellGUID, false);
|
HandleGameObject(DATA_EREKEM_CELL, false);
|
||||||
HandleGameObject(GO_ErekemCellGUID, false);
|
HandleGameObject(DATA_EREKEM_GUARD_2_CELL, false);
|
||||||
HandleGameObject(GO_ErekemRightGuardCellGUID, false);
|
HandleGameObject(DATA_EREKEM_GUARD_1_CELL, false);
|
||||||
HandleGameObject(GO_ErekemLeftGuardCellGUID, false);
|
HandleGameObject(DATA_ICHORON_CELL, false);
|
||||||
HandleGameObject(GO_IchoronCellGUID, false);
|
HandleGameObject(DATA_LAVANTHOR_CELL, false);
|
||||||
HandleGameObject(GO_LavanthorCellGUID, false);
|
HandleGameObject(DATA_XEVOZZ_CELL, false);
|
||||||
HandleGameObject(GO_XevozzCellGUID, false);
|
HandleGameObject(DATA_ZURAMAT_CELL, false);
|
||||||
HandleGameObject(GO_ZuramatCellGUID, false);
|
|
||||||
|
|
||||||
// respawn bosses
|
for (uint32 id = BOSS_MORAGG; id <= BOSS_ZURAMAT; ++id)
|
||||||
if (Creature* c = instance->GetCreature(NPC_MoraggGUID)) { c->DespawnOrUnsummon(); c->SetRespawnTime(3); c->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); c->SetImmuneToNPC(true); }
|
{
|
||||||
if (Creature* c = instance->GetCreature(NPC_MoraggGUID)) { c->DespawnOrUnsummon(); c->SetRespawnTime(3); c->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); c->SetImmuneToNPC(true); }
|
if (Creature* boss = GetCreature(id))
|
||||||
if (Creature* c = instance->GetCreature(NPC_ErekemGUID)) { c->DespawnOrUnsummon(); c->SetRespawnTime(3); c->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); c->SetImmuneToNPC(true); }
|
{
|
||||||
if (Creature* c = instance->GetCreature(NPC_ErekemGuardGUID[0])) { c->DespawnOrUnsummon(); c->SetRespawnTime(3); c->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); c->SetImmuneToNPC(true); }
|
boss->DespawnOrUnsummon();
|
||||||
if (Creature* c = instance->GetCreature(NPC_ErekemGuardGUID[1])) { c->DespawnOrUnsummon(); c->SetRespawnTime(3); c->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); c->SetImmuneToNPC(true); }
|
boss->SetRespawnTime(3);
|
||||||
if (Creature* c = instance->GetCreature(NPC_IchoronGUID)) { c->DespawnOrUnsummon(); c->SetRespawnTime(3); c->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); c->SetImmuneToNPC(true); }
|
boss->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
if (Creature* c = instance->GetCreature(NPC_LavanthorGUID)) { c->DespawnOrUnsummon(); c->SetRespawnTime(3); c->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); c->SetImmuneToNPC(true); }
|
boss->SetImmuneToNPC(true);
|
||||||
if (Creature* c = instance->GetCreature(NPC_XevozzGUID)) { c->DespawnOrUnsummon(); c->SetRespawnTime(3); c->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); c->SetImmuneToNPC(true); }
|
}
|
||||||
if (Creature* c = instance->GetCreature(NPC_ZuramatGUID)) { c->DespawnOrUnsummon(); c->SetRespawnTime(3); c->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); c->SetImmuneToNPC(true); }
|
}
|
||||||
if (Creature* c = instance->GetCreature(NPC_CyanigosaGUID)) { c->DespawnOrUnsummon(); }
|
if (Creature* guard1 = instance->GetCreature(_erekemGuardGuid[0]))
|
||||||
|
{
|
||||||
|
guard1->DespawnOrUnsummon();
|
||||||
|
guard1->SetRespawnTime(3);
|
||||||
|
guard1->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
|
guard1->SetImmuneToNPC(true);
|
||||||
|
}
|
||||||
|
if (Creature* guard2 = instance->GetCreature(_erekemGuardGuid[1]))
|
||||||
|
{
|
||||||
|
guard2->DespawnOrUnsummon();
|
||||||
|
guard2->SetRespawnTime(3);
|
||||||
|
guard2->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
|
guard2->SetImmuneToNPC(true);
|
||||||
|
}
|
||||||
|
if (Creature* cyanigosa = GetCreature(DATA_CYANIGOSA))
|
||||||
|
cyanigosa->DespawnOrUnsummon();
|
||||||
}
|
}
|
||||||
|
|
||||||
// reinitialize variables and events
|
|
||||||
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_SHOW, 0);
|
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_SHOW, 0);
|
||||||
EncounterStatus = NOT_STARTED;
|
_encounterStatus = NOT_STARTED;
|
||||||
GateHealth = 100;
|
_gateHealth = 100;
|
||||||
WaveCount = 0;
|
_waveCount = 0;
|
||||||
bDefensesUsed = false;
|
_defensesUsed = false;
|
||||||
if (m_auiEncounter[MAX_ENCOUNTER - 1] == DONE)
|
if (GetBossState(DATA_CYANIGOSA) == DONE)
|
||||||
EncounterStatus = DONE;
|
_encounterStatus = DONE;
|
||||||
events.Reset();
|
_events.Reset();
|
||||||
events.RescheduleEvent(EVENT_CHECK_PLAYERS, 5s);
|
_events.RescheduleEvent(EVENT_CHECK_PLAYERS, 5s);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/) override
|
bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/) override
|
||||||
@@ -653,35 +569,31 @@ public:
|
|||||||
switch (criteria_id)
|
switch (criteria_id)
|
||||||
{
|
{
|
||||||
case CRITERIA_DEFENSELESS:
|
case CRITERIA_DEFENSELESS:
|
||||||
return GateHealth == 100 && !bDefensesUsed;
|
return _gateHealth == 100 && !_defensesUsed;
|
||||||
case CRITERIA_A_VOID_DANCE:
|
case CRITERIA_A_VOID_DANCE:
|
||||||
case CRITERIA_DEHYDRATION:
|
case CRITERIA_DEHYDRATION:
|
||||||
return bAchiev;
|
return _achievementCompleted;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadSaveDataMore(std::istringstream& data) override
|
private:
|
||||||
{
|
bool _cleaned{ false };
|
||||||
EncounterStatus = NOT_STARTED;
|
uint8 _encounterStatus{ NOT_STARTED };
|
||||||
CLEANED = false;
|
EventMap _events;
|
||||||
events.Reset();
|
uint8 _gateHealth{ 100 };
|
||||||
events.RescheduleEvent(EVENT_CHECK_PLAYERS, 0ms);
|
uint8 _waveCount{ 0 };
|
||||||
|
uint8 _portalLocation{ 0 };
|
||||||
|
bool _achievementCompleted{ false };
|
||||||
|
bool _defensesUsed{ false };
|
||||||
|
|
||||||
data >> m_auiEncounter[0];
|
GuidVector _activationCrystalGuidList;
|
||||||
data >> m_auiEncounter[1];
|
|
||||||
data >> m_auiEncounter[2];
|
|
||||||
data >> uiFirstBoss;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteSaveDataMore(std::ostringstream& data) override
|
// Multi-instance creature tracking (can't use ObjectData)
|
||||||
{
|
ObjectGuid _guardGuid[4];
|
||||||
data << m_auiEncounter[0] << ' '
|
ObjectGuid _erekemGuardGuid[2];
|
||||||
<< m_auiEncounter[1] << ' '
|
|
||||||
<< m_auiEncounter[2] << ' '
|
GuidSet _trashMobs;
|
||||||
<< uiFirstBoss << ' '
|
|
||||||
<< uiSecondBoss << ' ';
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -18,15 +18,57 @@
|
|||||||
#ifndef DEF_VIOLET_HOLD_H
|
#ifndef DEF_VIOLET_HOLD_H
|
||||||
#define DEF_VIOLET_HOLD_H
|
#define DEF_VIOLET_HOLD_H
|
||||||
|
|
||||||
#define MAX_ENCOUNTER 3
|
|
||||||
|
|
||||||
#include "CreatureAIImpl.h"
|
#include "CreatureAIImpl.h"
|
||||||
|
|
||||||
#define DataHeader "VIO"
|
#define DataHeader "VIO"
|
||||||
|
|
||||||
#define VioletHoldScriptName "instance_violet_hold"
|
#define VioletHoldScriptName "instance_violet_hold"
|
||||||
|
|
||||||
enum Creatures
|
enum VHData
|
||||||
|
{
|
||||||
|
// Creature ObjectData IDs
|
||||||
|
// Boss creatures use VHBosses values directly (BOSS_MORAGG .. BOSS_ZURAMAT, DATA_CYANIGOSA)
|
||||||
|
DATA_SINCLARI = 10,
|
||||||
|
DATA_DOOR_SEAL,
|
||||||
|
DATA_TELEPORTATION_PORTAL,
|
||||||
|
|
||||||
|
// GO ObjectData IDs
|
||||||
|
DATA_MAIN_DOOR = 20,
|
||||||
|
DATA_MORAGG_CELL,
|
||||||
|
DATA_EREKEM_CELL,
|
||||||
|
DATA_EREKEM_GUARD_1_CELL,
|
||||||
|
DATA_EREKEM_GUARD_2_CELL,
|
||||||
|
DATA_ICHORON_CELL,
|
||||||
|
DATA_LAVANTHOR_CELL,
|
||||||
|
DATA_XEVOZZ_CELL,
|
||||||
|
DATA_ZURAMAT_CELL,
|
||||||
|
|
||||||
|
// Instance action/state IDs (used by SetData/GetData)
|
||||||
|
DATA_ENCOUNTER_STATUS = 30,
|
||||||
|
DATA_ACTIVATE_DEFENSE_SYSTEM,
|
||||||
|
DATA_START_INSTANCE,
|
||||||
|
DATA_ADD_TRASH_MOB,
|
||||||
|
DATA_DELETE_TRASH_MOB,
|
||||||
|
DATA_PORTAL_DEFEATED,
|
||||||
|
DATA_WAVE_COUNT,
|
||||||
|
DATA_PORTAL_LOCATION,
|
||||||
|
DATA_RELEASE_BOSS,
|
||||||
|
DATA_DECREASE_DOOR_HEALTH,
|
||||||
|
DATA_ACHIEV,
|
||||||
|
|
||||||
|
// Manual GUID tracking (multi-instance entries)
|
||||||
|
DATA_EREKEM_GUARD_1_GUID,
|
||||||
|
DATA_EREKEM_GUARD_2_GUID,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum VHPersistentData
|
||||||
|
{
|
||||||
|
PERSISTENT_DATA_FIRST_BOSS,
|
||||||
|
PERSISTENT_DATA_SECOND_BOSS,
|
||||||
|
PERSISTENT_DATA_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum VHCreatures
|
||||||
{
|
{
|
||||||
NPC_TELEPORTATION_PORTAL = 31011,
|
NPC_TELEPORTATION_PORTAL = 31011,
|
||||||
NPC_DEFENSE_SYSTEM = 30837,
|
NPC_DEFENSE_SYSTEM = 30837,
|
||||||
@@ -63,7 +105,7 @@ enum Creatures
|
|||||||
NPC_AZURE_STALKER = 32191,
|
NPC_AZURE_STALKER = 32191,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GameObjects
|
enum VHGameObjects
|
||||||
{
|
{
|
||||||
GO_MAIN_DOOR = 191723,
|
GO_MAIN_DOOR = 191723,
|
||||||
GO_XEVOZZ_DOOR = 191556,
|
GO_XEVOZZ_DOOR = 191556,
|
||||||
@@ -78,19 +120,25 @@ enum GameObjects
|
|||||||
GO_ACTIVATION_CRYSTAL = 193611,
|
GO_ACTIVATION_CRYSTAL = 193611,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Bosses
|
enum VHBosses
|
||||||
{
|
{
|
||||||
BOSS_NONE,
|
// Encounter slot IDs (used by SetBossState/GetBossState)
|
||||||
BOSS_MORAGG,
|
DATA_1ST_BOSS,
|
||||||
|
DATA_2ND_BOSS,
|
||||||
|
DATA_CYANIGOSA,
|
||||||
|
MAX_ENCOUNTER,
|
||||||
|
|
||||||
|
// Individual boss IDs (used by ObjectData and BossAI)
|
||||||
|
BOSS_MORAGG = MAX_ENCOUNTER,
|
||||||
BOSS_EREKEM,
|
BOSS_EREKEM,
|
||||||
BOSS_ICHORON,
|
BOSS_ICHORON,
|
||||||
BOSS_LAVANTHOR,
|
BOSS_LAVANTHOR,
|
||||||
BOSS_XEVOZZ,
|
BOSS_XEVOZZ,
|
||||||
BOSS_ZURAMAT,
|
BOSS_ZURAMAT,
|
||||||
BOSS_CYANIGOSA
|
MAX_BOSS
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Spells
|
enum VHSpells
|
||||||
{
|
{
|
||||||
SPELL_CONTROL_CRYSTAL_ACTIVATION = 57804,
|
SPELL_CONTROL_CRYSTAL_ACTIVATION = 57804,
|
||||||
SPELL_DEFENSE_SYSTEM_SPAWN_EFFECT = 57886,
|
SPELL_DEFENSE_SYSTEM_SPAWN_EFFECT = 57886,
|
||||||
@@ -104,7 +152,7 @@ enum Spells
|
|||||||
SPELL_CYANIGOSA_BLUE_AURA = 45870
|
SPELL_CYANIGOSA_BLUE_AURA = 45870
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Events
|
enum VHInstanceEvents
|
||||||
{
|
{
|
||||||
EVENT_CHECK_PLAYERS = 1,
|
EVENT_CHECK_PLAYERS = 1,
|
||||||
EVENT_GUARDS_FALL_BACK,
|
EVENT_GUARDS_FALL_BACK,
|
||||||
@@ -112,7 +160,7 @@ enum Events
|
|||||||
EVENT_SINCLARI_FALL_BACK,
|
EVENT_SINCLARI_FALL_BACK,
|
||||||
EVENT_START_ENCOUNTER,
|
EVENT_START_ENCOUNTER,
|
||||||
EVENT_SUMMON_PORTAL,
|
EVENT_SUMMON_PORTAL,
|
||||||
EVENT_CYANIGOSSA_TRANSFORM,
|
EVENT_CYANIGOSA_TRANSFORM,
|
||||||
EVENT_CYANIGOSA_ATTACK,
|
EVENT_CYANIGOSA_ATTACK,
|
||||||
|
|
||||||
// Event defense system
|
// Event defense system
|
||||||
@@ -120,32 +168,7 @@ enum Events
|
|||||||
EVENT_ARCANE_LIGHTNING_INSTAKILL
|
EVENT_ARCANE_LIGHTNING_INSTAKILL
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Data
|
enum VHAchievCriteria
|
||||||
{
|
|
||||||
DATA_ACTIVATE_DEFENSE_SYSTEM = 1,
|
|
||||||
DATA_ENCOUNTER_STATUS,
|
|
||||||
DATA_START_INSTANCE,
|
|
||||||
DATA_ADD_TRASH_MOB,
|
|
||||||
DATA_DELETE_TRASH_MOB,
|
|
||||||
DATA_PORTAL_DEFEATED,
|
|
||||||
DATA_WAVE_COUNT,
|
|
||||||
DATA_PORTAL_LOCATION,
|
|
||||||
DATA_TELEPORTATION_PORTAL_GUID,
|
|
||||||
DATA_DOOR_SEAL_GUID,
|
|
||||||
DATA_FIRST_BOSS_NUMBER,
|
|
||||||
DATA_SECOND_BOSS_NUMBER,
|
|
||||||
DATA_RELEASE_BOSS,
|
|
||||||
DATA_DECRASE_DOOR_HEALTH,
|
|
||||||
DATA_BOSS_DIED,
|
|
||||||
DATA_FAILED,
|
|
||||||
DATA_EREKEM_GUID,
|
|
||||||
DATA_EREKEM_GUARD_1_GUID,
|
|
||||||
DATA_EREKEM_GUARD_2_GUID,
|
|
||||||
DATA_ICHORON_GUID,
|
|
||||||
DATA_ACHIEV,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum AchievCriteria
|
|
||||||
{
|
{
|
||||||
CRITERIA_DEFENSELESS = 6803,
|
CRITERIA_DEFENSELESS = 6803,
|
||||||
CRITERIA_A_VOID_DANCE = 7587,
|
CRITERIA_A_VOID_DANCE = 7587,
|
||||||
@@ -308,4 +331,6 @@ inline AI* GetVioletHoldAI(T* obj)
|
|||||||
return GetInstanceAI<AI>(obj, VioletHoldScriptName);
|
return GetInstanceAI<AI>(obj, VioletHoldScriptName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RegisterVioletHoldCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetVioletHoldAI)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user