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:
parent
25b928b094
commit
272da9fbad
12 changed files with 1745 additions and 2222 deletions
|
|
@ -1810,12 +1810,13 @@ void Map::RemoveAllObjectsInRemoveList()
|
|||
}
|
||||
}
|
||||
|
||||
uint32 Map::GetPlayersCountExceptGMs() const
|
||||
uint32 Map::GetPlayersCountExceptGMs(bool aliveOnly /*= false*/) const
|
||||
{
|
||||
uint32 count = 0;
|
||||
for (MapRefMgr::const_iterator itr = m_mapRefMgr.begin(); itr != m_mapRefMgr.end(); ++itr)
|
||||
if (!itr->GetSource()->IsGameMaster())
|
||||
++count;
|
||||
for (auto const& ref : m_mapRefMgr)
|
||||
if (Player* player = ref.GetSource())
|
||||
if (!player->IsGameMaster() && (!aliveOnly || (player->IsAlive() && !player->HasSpiritOfRedemptionAura())))
|
||||
++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -318,7 +318,8 @@ public:
|
|||
void markCell(uint32 pCellId) { marked_cells.set(pCellId); }
|
||||
|
||||
[[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;
|
||||
|
||||
|
|
|
|||
|
|
@ -50,141 +50,95 @@ enum eEvents
|
|||
EVENT_UNROOT,
|
||||
};
|
||||
|
||||
class boss_cyanigosa : public CreatureScript
|
||||
struct boss_cyanigosa : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_cyanigosa() : CreatureScript("boss_cyanigosa") { }
|
||||
boss_cyanigosa(Creature* c) : BossAI(c, DATA_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;
|
||||
EventMap events;
|
||||
|
||||
void Reset() override
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
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
|
||||
{
|
||||
DoZoneInCombat();
|
||||
Talk(SAY_AGGRO);
|
||||
events.Reset();
|
||||
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 KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim && victim->GetGUID() == me->GetGUID())
|
||||
return;
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void SpellHitTarget(Unit* target, SpellInfo const* spell) 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 MoveInLineOfSight(Unit* /*who*/) override {}
|
||||
|
||||
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_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 EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
_EnterEvadeMode(why);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_cyanigosa()
|
||||
{
|
||||
new boss_cyanigosa();
|
||||
RegisterVioletHoldCreatureAI(boss_cyanigosa);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,6 @@ enum eSpells
|
|||
SPELL_BREAK_BONDS = 59463,
|
||||
SPELL_CHAIN_HEAL = 54481,
|
||||
SPELL_EARTH_SHIELD = 54479,
|
||||
//SPELL_EARTH_SHIELD_TRIGGERED_N = 54480,
|
||||
//SPELL_EARTH_SHIELD_TRIGGERED_H = 59472,
|
||||
SPELL_EARTH_SHOCK = 54511,
|
||||
SPELL_LIGHTNING_BOLT = 53044,
|
||||
SPELL_STORMSTRIKE = 51876,
|
||||
|
|
@ -53,164 +51,120 @@ enum eEvents
|
|||
EVENT_SPELL_STORMSTRIKE,
|
||||
};
|
||||
|
||||
class boss_erekem : public CreatureScript
|
||||
struct boss_erekem : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_erekem() : CreatureScript("boss_erekem") { }
|
||||
boss_erekem(Creature* c) : BossAI(c, 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;
|
||||
EventMap events;
|
||||
|
||||
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* 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()))
|
||||
{
|
||||
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()) // both dead
|
||||
me->CastSpell(me->GetVictim(), SPELL_STORMSTRIKE, false);
|
||||
events.Repeat(3s);
|
||||
events.Repeat(3s, 6s);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
events.Repeat(8s, 11s);
|
||||
break;
|
||||
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
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_BOSS_DIED, 0);
|
||||
}
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim && victim->GetGUID() == me->GetGUID())
|
||||
return;
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim && victim->GetGUID() == me->GetGUID())
|
||||
return;
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||
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);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
_EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
ObjectGuid GetChainHealTargetGuid()
|
||||
{
|
||||
if (HealthBelowPct(85))
|
||||
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
|
||||
|
|
@ -227,81 +181,69 @@ enum eGuardEvents
|
|||
EVENT_SPELL_STRIKE
|
||||
};
|
||||
|
||||
class npc_erekem_guard : public CreatureScript
|
||||
struct npc_erekem_guard : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_erekem_guard() : CreatureScript("npc_erekem_guard") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* pCreature) const override
|
||||
npc_erekem_guard(Creature* c) : ScriptedAI(c)
|
||||
{
|
||||
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;
|
||||
EventMap events;
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
}
|
||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||
|
||||
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 = 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 {}
|
||||
};
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
void AddSC_boss_erekem()
|
||||
{
|
||||
new boss_erekem();
|
||||
new npc_erekem_guard();
|
||||
RegisterVioletHoldCreatureAI(boss_erekem);
|
||||
RegisterVioletHoldCreatureAI(npc_erekem_guard);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,302 +58,278 @@ enum eSpells
|
|||
SPELL_WATER_BLAST = 54237,
|
||||
SPELL_WATER_BOLT_VOLLEY = 54241,
|
||||
|
||||
SPELL_SPLASH = 59516, // casted by globule upon death
|
||||
SPELL_WATER_GLOBULE = 54268, // casted when hit by visual
|
||||
SPELL_CREATE_GLOBULE_VISUAL = 54260, // tar 25
|
||||
SPELL_SPLASH = 59516,
|
||||
SPELL_WATER_GLOBULE = 54268,
|
||||
SPELL_CREATE_GLOBULE_VISUAL = 54260,
|
||||
};
|
||||
|
||||
class boss_ichoron : public CreatureScript
|
||||
enum eEvents
|
||||
{
|
||||
public:
|
||||
boss_ichoron() : CreatureScript("boss_ichoron") { }
|
||||
EVENT_WATER_BOLT_VOLLEY = 1,
|
||||
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;
|
||||
SummonList globules;
|
||||
bool bIsExploded;
|
||||
bool bIsFrenzy;
|
||||
uint32 uiWaterBoltVolleyTimer;
|
||||
uint32 uiDrainedTimer;
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetDisplayId(me->GetNativeDisplayId());
|
||||
}
|
||||
|
||||
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();
|
||||
bIsExploded = false;
|
||||
bIsFrenzy = false;
|
||||
uiDrainedTimer = 15000;
|
||||
uiWaterBoltVolleyTimer = urand(7000, 12000);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetDisplayId(me->GetNativeDisplayId());
|
||||
Talk(SAY_ENRAGE);
|
||||
DoCastSelf(SPELL_FRENZY, true);
|
||||
_isFrenzy = true;
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
if (!_isFrenzy)
|
||||
{
|
||||
if (!me->IsAlive())
|
||||
return;
|
||||
|
||||
switch (param)
|
||||
if (!_isExploded)
|
||||
{
|
||||
case ACTION_WATER_ELEMENT_HIT:
|
||||
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))
|
||||
{
|
||||
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);
|
||||
Talk(SAY_SHATTER);
|
||||
DoZoneInCombat();
|
||||
IchoronDoCastToAllHostilePlayers(SPELL_WATER_BLAST, true);
|
||||
me->CastSpell(me, SPELL_DRAINED, true);
|
||||
bIsExploded = true;
|
||||
uiDrainedTimer = 15000;
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
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);
|
||||
}
|
||||
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
|
||||
{
|
||||
if (uiDrainedTimer <= uiDiff)
|
||||
DoExplodeCompleted();
|
||||
else
|
||||
bool isWaterElementsAlive = false;
|
||||
if (!summons.empty())
|
||||
{
|
||||
uiDrainedTimer -= uiDiff;
|
||||
|
||||
bool bIsWaterElementsAlive = false;
|
||||
if (!globules.empty())
|
||||
{
|
||||
for (ObjectGuid const& guid : globules)
|
||||
if (Creature* pTemp = ObjectAccessor::GetCreature(*me, guid))
|
||||
if (pTemp->IsAlive())
|
||||
{
|
||||
bIsWaterElementsAlive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bIsWaterElementsAlive)
|
||||
DoExplodeCompleted();
|
||||
for (ObjectGuid const& guid : summons)
|
||||
if (Creature* temp = ObjectAccessor::GetCreature(*me, guid))
|
||||
if (temp->IsAlive())
|
||||
{
|
||||
isWaterElementsAlive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
pSummoned->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
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());
|
||||
DoCastAOE(SPELL_WATER_BOLT_VOLLEY);
|
||||
events.Repeat(10s, 15s);
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* pSummoned) override
|
||||
{
|
||||
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);
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
struct npc_ichor_globuleAI : public ScriptedAI
|
||||
void JustSummoned(Creature* summoned) override
|
||||
{
|
||||
npc_ichor_globuleAI(Creature* c) : ScriptedAI(c)
|
||||
if (summoned)
|
||||
{
|
||||
pInstance = c->GetInstanceScript();
|
||||
uiRangeCheck_Timer = 1000;
|
||||
summoned->SetSpeed(MOVE_RUN, 0.3f);
|
||||
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;
|
||||
uint32 uiRangeCheck_Timer;
|
||||
|
||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
||||
void SummonedCreatureDespawn(Creature* summoned) override
|
||||
{
|
||||
if (summoned)
|
||||
{
|
||||
if (spell->Id == SPELL_CREATE_GLOBULE_VISUAL)
|
||||
me->CastSpell(me, SPELL_WATER_GLOBULE, true);
|
||||
BossAI::SummonedCreatureDespawn(summoned);
|
||||
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 (pInstance)
|
||||
if (Creature* pIchoron = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_ICHORON_GUID)))
|
||||
if (me->IsWithinDist(pIchoron, 2.0f, false))
|
||||
{
|
||||
if (pIchoron->AI())
|
||||
pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_HIT);
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
uiRangeCheck_Timer = 1000;
|
||||
}
|
||||
else uiRangeCheck_Timer -= uiDiff;
|
||||
if (Creature* ichoron = _instance->GetCreature(BOSS_ICHORON))
|
||||
if (me->IsWithinDist(ichoron, 2.0f, false))
|
||||
{
|
||||
if (ichoron->AI())
|
||||
ichoron->AI()->DoAction(ACTION_WATER_ELEMENT_HIT);
|
||||
me->DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
_events.Repeat(1s);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
me->CastSpell(me, SPELL_SPLASH, true);
|
||||
if (pInstance)
|
||||
if (Creature* pIchoron = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_ICHORON_GUID)))
|
||||
if (pIchoron->AI())
|
||||
pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_KILLED);
|
||||
me->DespawnOrUnsummon(2500ms);
|
||||
}
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
DoCastSelf(SPELL_SPLASH, true);
|
||||
if (Creature* ichoron = _instance->GetCreature(BOSS_ICHORON))
|
||||
if (ichoron->AI())
|
||||
ichoron->AI()->DoAction(ACTION_WATER_ELEMENT_KILLED);
|
||||
me->DespawnOrUnsummon(2500ms);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* /*who*/) override {}
|
||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||
};
|
||||
void AttackStart(Unit* /*who*/) override {}
|
||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
void AddSC_boss_ichoron()
|
||||
{
|
||||
new boss_ichoron();
|
||||
new npc_ichor_globule();
|
||||
RegisterVioletHoldCreatureAI(boss_ichoron);
|
||||
RegisterVioletHoldCreatureAI(npc_ichor_globule);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,97 +35,53 @@ enum eEvents
|
|||
EVENT_SPELL_CAUTERIZING_FLAMES,
|
||||
};
|
||||
|
||||
class boss_lavanthor : public CreatureScript
|
||||
struct boss_lavanthor : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_lavanthor() : CreatureScript("boss_lavanthor") { }
|
||||
boss_lavanthor(Creature* c) : BossAI(c, 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;
|
||||
EventMap events;
|
||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
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 EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
_EnterEvadeMode(why);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_lavanthor()
|
||||
{
|
||||
new boss_lavanthor();
|
||||
RegisterVioletHoldCreatureAI(boss_lavanthor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,12 +25,7 @@
|
|||
enum eSpells
|
||||
{
|
||||
SPELL_RAY_OF_SUFFERING = 54442,
|
||||
//SPELL_RAY_OF_SUFFERING_TRIGGERED = 54417,
|
||||
|
||||
SPELL_RAY_OF_PAIN = 54438,
|
||||
//SPELL_RAY_OF_PAIN_TRIGGERED_N = 54416,
|
||||
//SPELL_RAY_OF_PAIN_TRIGGERED_H = 59525,
|
||||
|
||||
SPELL_CORROSIVE_SALIVA = 54527,
|
||||
SPELL_OPTIC_LINK = 54396,
|
||||
};
|
||||
|
|
@ -41,90 +36,46 @@ enum eEvents
|
|||
EVENT_SPELL_OPTIC_LINK,
|
||||
};
|
||||
|
||||
class boss_moragg : public CreatureScript
|
||||
struct boss_moragg : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_moragg() : CreatureScript("boss_moragg") { }
|
||||
boss_moragg(Creature* c) : BossAI(c, 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;
|
||||
EventMap events;
|
||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
_EnterEvadeMode(why);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_optic_link_aura : public AuraScript
|
||||
|
|
@ -147,6 +98,6 @@ class spell_optic_link_aura : public AuraScript
|
|||
|
||||
void AddSC_boss_moragg()
|
||||
{
|
||||
new boss_moragg();
|
||||
RegisterVioletHoldCreatureAI(boss_moragg);
|
||||
RegisterSpellScript(spell_optic_link_aura);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,8 +39,6 @@ enum eSpells
|
|||
SPELL_SUMMON_ETHEREAL_SPHERE_3 = 54138,
|
||||
|
||||
SPELL_ARCANE_POWER = 54160
|
||||
//SPELL_SUMMON_PLAYERS = 54164, // not used
|
||||
//SPELL_POWER_BALL_VISUAL = 54141,
|
||||
};
|
||||
|
||||
enum eEvents
|
||||
|
|
@ -51,159 +49,114 @@ enum eEvents
|
|||
EVENT_CHECK_DISTANCE,
|
||||
};
|
||||
|
||||
class boss_xevozz : public CreatureScript
|
||||
struct boss_xevozz : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_xevozz() : CreatureScript("boss_xevozz") { }
|
||||
boss_xevozz(Creature* c) : BossAI(c, 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();
|
||||
}
|
||||
|
||||
InstanceScript* pInstance;
|
||||
EventMap events;
|
||||
SummonList spheres;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
spheres.DespawnAll();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
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:
|
||||
case EVENT_SPELL_ARCANE_BARRAGE_VOLLEY:
|
||||
DoCastAOE(SPELL_ARCANE_BARRAGE_VOLLEY);
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
case EVENT_SPELL_ARCANE_BUFFET:
|
||||
DoCastVictim(SPELL_ARCANE_BUFFET);
|
||||
break;
|
||||
case EVENT_SUMMON_SPHERES:
|
||||
{
|
||||
Talk(SAY_SUMMON_ENERGY);
|
||||
summons.DespawnAll();
|
||||
uint32 entry1 = RAND(SPELL_SUMMON_ETHEREAL_SPHERE_1, SPELL_SUMMON_ETHEREAL_SPHERE_2, SPELL_SUMMON_ETHEREAL_SPHERE_3);
|
||||
DoCastAOE(entry1, true);
|
||||
if (IsHeroic())
|
||||
{
|
||||
Talk(SAY_SUMMON_ENERGY);
|
||||
spheres.DespawnAll();
|
||||
uint32 entry1 = RAND(SPELL_SUMMON_ETHEREAL_SPHERE_1, SPELL_SUMMON_ETHEREAL_SPHERE_2, SPELL_SUMMON_ETHEREAL_SPHERE_3);
|
||||
me->CastSpell((Unit*)nullptr, entry1, 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);
|
||||
uint32 entry2;
|
||||
do { entry2 = RAND(SPELL_SUMMON_ETHEREAL_SPHERE_1, SPELL_SUMMON_ETHEREAL_SPHERE_2, SPELL_SUMMON_ETHEREAL_SPHERE_3); }
|
||||
while (entry1 == entry2);
|
||||
DoCastAOE(entry2, true);
|
||||
}
|
||||
break;
|
||||
case EVENT_CHECK_DISTANCE:
|
||||
events.Repeat(45s);
|
||||
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;
|
||||
if (pInstance)
|
||||
for (ObjectGuid const& guid : spheres)
|
||||
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);
|
||||
Talk(SAY_CHARGED);
|
||||
events.Repeat(9s);
|
||||
events.RescheduleEvent(EVENT_SUMMON_SPHERES, 10s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
else
|
||||
events.Repeat(2s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* pSummoned) override
|
||||
void JustSummoned(Creature* summoned) override
|
||||
{
|
||||
if (summoned)
|
||||
{
|
||||
if (pSummoned)
|
||||
{
|
||||
pSummoned->GetMotionMaster()->MoveFollow(me, 0.0f, 0.0f, MOTION_SLOT_ACTIVE, true, false);
|
||||
spheres.Summon(pSummoned);
|
||||
if (pInstance)
|
||||
pInstance->SetGuidData(DATA_ADD_TRASH_MOB, pSummoned->GetGUID());
|
||||
}
|
||||
summoned->GetMotionMaster()->MoveFollow(me, 0.0f, 0.0f, MOTION_SLOT_ACTIVE, true, false);
|
||||
BossAI::JustSummoned(summoned);
|
||||
instance->SetGuidData(DATA_ADD_TRASH_MOB, summoned->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* pSummoned) override
|
||||
void SummonedCreatureDespawn(Creature* summoned) override
|
||||
{
|
||||
if (summoned)
|
||||
{
|
||||
if (pSummoned)
|
||||
{
|
||||
spheres.Despawn(pSummoned);
|
||||
if (pInstance)
|
||||
pInstance->SetGuidData(DATA_DELETE_TRASH_MOB, pSummoned->GetGUID());
|
||||
}
|
||||
BossAI::SummonedCreatureDespawn(summoned);
|
||||
instance->SetGuidData(DATA_DELETE_TRASH_MOB, summoned->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
spheres.DespawnAll();
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_BOSS_DIED, 0);
|
||||
}
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* pVictim) override
|
||||
{
|
||||
if (pVictim && pVictim->GetGUID() == me->GetGUID())
|
||||
return;
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim && victim->GetGUID() == me->GetGUID())
|
||||
return;
|
||||
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||
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);
|
||||
}
|
||||
};
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
_EnterEvadeMode(why);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_xevozz()
|
||||
{
|
||||
new boss_xevozz();
|
||||
RegisterVioletHoldCreatureAI(boss_xevozz);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ enum eSpells
|
|||
SPELL_VOID_SHIFT = 54361,
|
||||
SPELL_SUMMON_VOID_SENTRY = 54369,
|
||||
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
|
||||
{
|
||||
|
|
@ -50,208 +50,154 @@ enum eEvents
|
|||
EVENT_SPELL_SUMMON_VOID_SENTRY,
|
||||
};
|
||||
|
||||
class boss_zuramat : public CreatureScript
|
||||
enum eVoidSentryEvents
|
||||
{
|
||||
public:
|
||||
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);
|
||||
}
|
||||
};
|
||||
EVENT_CHECK_SUMMONER = 1,
|
||||
};
|
||||
|
||||
class npc_vh_void_sentry : public CreatureScript
|
||||
struct boss_zuramat : public BossAI
|
||||
{
|
||||
public:
|
||||
npc_vh_void_sentry() : CreatureScript("npc_vh_void_sentry") { }
|
||||
boss_zuramat(Creature* c) : BossAI(c, BOSS_ZURAMAT) { }
|
||||
|
||||
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();
|
||||
SummonedGUID.Clear();
|
||||
checkTimer = 5000;
|
||||
//me->CastSpell(me, SPELL_SUMMON_VOID_SENTRY_BALL, true);
|
||||
if (Creature* pSummoned = me->SummonCreature(NPC_VOID_SENTRY_BALL, *me, TEMPSUMMON_TIMED_DESPAWN, 300000))
|
||||
{
|
||||
pSummoned->SetPhaseMask(1, true);
|
||||
SummonedGUID = pSummoned->GetGUID();
|
||||
pInstance->SetGuidData(DATA_ADD_TRASH_MOB, pSummoned->GetGUID());
|
||||
}
|
||||
case EVENT_SPELL_SHROUD_OF_DARKNESS:
|
||||
DoCastSelf(SPELL_SHROUD_OF_DARKNESS);
|
||||
Talk(SAY_SHIELD);
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
case EVENT_SPELL_VOID_SHIFT:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
|
||||
{
|
||||
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;
|
||||
ObjectGuid SummonedGUID;
|
||||
uint16 checkTimer;
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
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)
|
||||
if (Creature* c = pInstance->instance->GetCreature(SummonedGUID))
|
||||
c->DespawnOrUnsummon();
|
||||
BossAI::JustSummoned(summoned);
|
||||
summoned->SetPhaseMask(16, true);
|
||||
instance->SetGuidData(DATA_ADD_TRASH_MOB, summoned->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
void SummonedCreatureDespawn(Creature* summoned) override
|
||||
{
|
||||
if (summoned)
|
||||
{
|
||||
if (pInstance)
|
||||
{
|
||||
pInstance->SetData(DATA_ACHIEV, 0);
|
||||
if (Creature* c = pInstance->instance->GetCreature(SummonedGUID))
|
||||
c->DespawnOrUnsummon();
|
||||
}
|
||||
me->DespawnOrUnsummon(5s);
|
||||
BossAI::SummonedCreatureDespawn(summoned);
|
||||
if (summoned->IsAIEnabled)
|
||||
summoned->AI()->DoAction(-1337);
|
||||
instance->SetGuidData(DATA_DELETE_TRASH_MOB, summoned->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* pSummoned) override
|
||||
{
|
||||
if (pSummoned)
|
||||
pInstance->SetGuidData(DATA_DELETE_TRASH_MOB, pSummoned->GetGUID());
|
||||
}
|
||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||
|
||||
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)
|
||||
{
|
||||
checkTimer = 5000;
|
||||
bool good = false;
|
||||
if (me->IsSummon())
|
||||
if (Unit* s = me->ToTempSummon()->GetSummonerUnit())
|
||||
if (s->IsAlive())
|
||||
good = true;
|
||||
if (!good)
|
||||
me->KillSelf();
|
||||
}
|
||||
else
|
||||
checkTimer -= diff;
|
||||
summoned->SetPhaseMask(1, true);
|
||||
_summonedGuid = summoned->GetGUID();
|
||||
_instance->SetGuidData(DATA_ADD_TRASH_MOB, summoned->GetGUID());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
new boss_zuramat();
|
||||
new npc_vh_void_sentry();
|
||||
RegisterVioletHoldCreatureAI(boss_zuramat);
|
||||
RegisterVioletHoldCreatureAI(npc_vh_void_sentry);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include "WorldStateDefines.h"
|
||||
#include "violet_hold.h"
|
||||
|
||||
enum vYells
|
||||
enum VHYells
|
||||
{
|
||||
CYANIGOSA_SAY_SPAWN = 3,
|
||||
SAY_SINCLARI_LEAVING = 0,
|
||||
|
|
@ -30,175 +30,163 @@ enum vYells
|
|||
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
|
||||
{
|
||||
public:
|
||||
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
|
||||
{
|
||||
instance_violet_hold_InstanceMapScript(Map* pMap) : InstanceScript(pMap) {}
|
||||
|
||||
uint32 m_auiEncounter[MAX_ENCOUNTER];
|
||||
bool CLEANED;
|
||||
uint8 EncounterStatus;
|
||||
uint32 uiFirstBoss, uiSecondBoss;
|
||||
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;
|
||||
instance_violet_hold_InstanceMapScript(Map* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(MAX_BOSS);
|
||||
SetPersistentDataCount(PERSISTENT_DATA_COUNT);
|
||||
LoadObjectData(creatureData, goData);
|
||||
}
|
||||
|
||||
void Initialize() override
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
|
||||
CLEANED = false;
|
||||
EncounterStatus = NOT_STARTED;
|
||||
uiFirstBoss = 0;
|
||||
uiSecondBoss = 0;
|
||||
events.Reset();
|
||||
events.RescheduleEvent(EVENT_CHECK_PLAYERS, 0ms);
|
||||
GateHealth = 100;
|
||||
WaveCount = 0;
|
||||
PortalLocation = 0;
|
||||
bDefensesUsed = false;
|
||||
_cleaned = false;
|
||||
_encounterStatus = NOT_STARTED;
|
||||
_events.Reset();
|
||||
_events.RescheduleEvent(EVENT_CHECK_PLAYERS, 0ms);
|
||||
_gateHealth = 100;
|
||||
_waveCount = 0;
|
||||
_portalLocation = 0;
|
||||
_defensesUsed = false;
|
||||
|
||||
GO_ActivationCrystalGUID.clear();
|
||||
_activationCrystalGuidList.clear();
|
||||
}
|
||||
|
||||
bool IsEncounterInProgress() const override
|
||||
{
|
||||
return false;
|
||||
return _encounterStatus == IN_PROGRESS;
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_SINCLARI:
|
||||
NPC_SinclariGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_VIOLET_HOLD_GUARD:
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
if (!NPC_GuardGUID[i])
|
||||
for (ObjectGuid& guid : _guardGuid)
|
||||
if (!guid)
|
||||
{
|
||||
NPC_GuardGUID[i] = creature->GetGUID();
|
||||
guid = creature->GetGUID();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NPC_DEFENSE_DUMMY_TARGET:
|
||||
creature->ApplySpellImmune(0, IMMUNITY_ID, SPELL_ARCANE_LIGHTNING, true);
|
||||
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:
|
||||
if (!NPC_ErekemGuardGUID[0])
|
||||
NPC_ErekemGuardGUID[0] = creature->GetGUID();
|
||||
if (!_erekemGuardGuid[0])
|
||||
_erekemGuardGuid[0] = creature->GetGUID();
|
||||
else
|
||||
NPC_ErekemGuardGUID[1] = creature->GetGUID();
|
||||
break;
|
||||
case NPC_MORAGG:
|
||||
NPC_MoraggGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_CYANIGOSA:
|
||||
NPC_CyanigosaGUID = creature->GetGUID();
|
||||
_erekemGuardGuid[1] = creature->GetGUID();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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); // make go not used yet
|
||||
go->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE); // not useable at the beginning
|
||||
GO_ActivationCrystalGUID.push_back(go->GetGUID());
|
||||
HandleGameObject(ObjectGuid::Empty, false, go);
|
||||
go->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
_activationCrystalGuidList.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;
|
||||
case GO_MAIN_DOOR:
|
||||
GO_MainGateGUID = go->GetGUID();
|
||||
case DATA_CYANIGOSA:
|
||||
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;
|
||||
// BOSS GATES BELOW:
|
||||
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();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
|
|
@ -208,90 +196,57 @@ public:
|
|||
case DATA_ACTIVATE_DEFENSE_SYSTEM:
|
||||
{
|
||||
if (data)
|
||||
bDefensesUsed = true;
|
||||
const Position pos = {1919.09546f, 812.29724f, 86.2905f, M_PI};
|
||||
_defensesUsed = true;
|
||||
Position const pos = {1919.09546f, 812.29724f, 86.2905f, M_PI};
|
||||
instance->SummonCreature(NPC_DEFENSE_SYSTEM, pos, 0, 6499);
|
||||
}
|
||||
break;
|
||||
case DATA_START_INSTANCE:
|
||||
if (EncounterStatus == NOT_STARTED)
|
||||
if (_encounterStatus == NOT_STARTED)
|
||||
{
|
||||
EncounterStatus = IN_PROGRESS;
|
||||
if (Creature* c = instance->GetCreature(NPC_SinclariGUID))
|
||||
_encounterStatus = IN_PROGRESS;
|
||||
if (Creature* sinclari = GetCreature(DATA_SINCLARI))
|
||||
{
|
||||
c->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
c->AI()->Talk(SAY_SINCLARI_LEAVING);
|
||||
/// @todo: Missing orientation for Sinclari's movement and "interaction" animation with the nearby crystal.
|
||||
sinclari->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
sinclari->AI()->Talk(SAY_SINCLARI_LEAVING);
|
||||
}
|
||||
events.RescheduleEvent(EVENT_GUARDS_FALL_BACK, 4s);
|
||||
_events.RescheduleEvent(EVENT_GUARDS_FALL_BACK, 4s);
|
||||
}
|
||||
break;
|
||||
case DATA_PORTAL_DEFEATED:
|
||||
events.RescheduleEvent(EVENT_SUMMON_PORTAL, 3s);
|
||||
_events.RescheduleEvent(EVENT_SUMMON_PORTAL, 3s);
|
||||
break;
|
||||
case DATA_PORTAL_LOCATION:
|
||||
PortalLocation = data;
|
||||
_portalLocation = data;
|
||||
break;
|
||||
case DATA_DECRASE_DOOR_HEALTH:
|
||||
if (GateHealth > 0)
|
||||
--GateHealth;
|
||||
if (GateHealth == 0)
|
||||
case DATA_DECREASE_DOOR_HEALTH:
|
||||
if (_gateHealth > 0)
|
||||
--_gateHealth;
|
||||
if (_gateHealth == 0)
|
||||
{
|
||||
CLEANED = false;
|
||||
_cleaned = false;
|
||||
InstanceCleanup();
|
||||
}
|
||||
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_PRISON_STATE, (uint32)GateHealth);
|
||||
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_PRISON_STATE, (uint32)_gateHealth);
|
||||
break;
|
||||
case DATA_RELEASE_BOSS:
|
||||
if (WaveCount == 6)
|
||||
StartBossEncounter(uiFirstBoss);
|
||||
if (_waveCount == 6)
|
||||
StartBossEncounter(GetPersistentData(PERSISTENT_DATA_FIRST_BOSS));
|
||||
else
|
||||
StartBossEncounter(uiSecondBoss);
|
||||
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();
|
||||
StartBossEncounter(GetPersistentData(PERSISTENT_DATA_SECOND_BOSS));
|
||||
break;
|
||||
case DATA_ACHIEV:
|
||||
bAchiev = !!data;
|
||||
_achievementCompleted = !!data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SetGuidData(uint32 type, ObjectGuid data) override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_ADD_TRASH_MOB:
|
||||
trashMobs.insert(data);
|
||||
break;
|
||||
case DATA_DELETE_TRASH_MOB:
|
||||
if (!CLEANED)
|
||||
trashMobs.erase(data);
|
||||
break;
|
||||
}
|
||||
if (type == DATA_ADD_TRASH_MOB)
|
||||
_trashMobs.insert(data);
|
||||
else if (type == DATA_DELETE_TRASH_MOB && !_cleaned)
|
||||
_trashMobs.erase(data);
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
|
|
@ -299,15 +254,11 @@ public:
|
|||
switch (type)
|
||||
{
|
||||
case DATA_ENCOUNTER_STATUS:
|
||||
return (uint32)EncounterStatus;
|
||||
return (uint32)_encounterStatus;
|
||||
case DATA_WAVE_COUNT:
|
||||
return (uint32)WaveCount;
|
||||
return (uint32)_waveCount;
|
||||
case DATA_PORTAL_LOCATION:
|
||||
return PortalLocation;
|
||||
case DATA_FIRST_BOSS_NUMBER:
|
||||
return uiFirstBoss;
|
||||
case DATA_SECOND_BOSS_NUMBER:
|
||||
return uiSecondBoss;
|
||||
return _portalLocation;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -315,212 +266,180 @@ public:
|
|||
|
||||
ObjectGuid GetGuidData(uint32 identifier) const override
|
||||
{
|
||||
switch (identifier)
|
||||
{
|
||||
case DATA_TELEPORTATION_PORTAL_GUID:
|
||||
return NPC_PortalGUID;
|
||||
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;
|
||||
}
|
||||
|
||||
if (identifier == DATA_EREKEM_GUARD_1_GUID)
|
||||
return _erekemGuardGuid[0];
|
||||
if (identifier == DATA_EREKEM_GUARD_2_GUID)
|
||||
return _erekemGuardGuid[1];
|
||||
return ObjectGuid::Empty;
|
||||
}
|
||||
|
||||
void StartBossEncounter(uint8 uiBoss)
|
||||
void StartBossEncounter(uint32 bossId)
|
||||
{
|
||||
Creature* pBoss = nullptr;
|
||||
|
||||
switch (uiBoss)
|
||||
switch (bossId)
|
||||
{
|
||||
case BOSS_MORAGG:
|
||||
HandleGameObject(GO_MoraggCellGUID, true);
|
||||
pBoss = instance->GetCreature(NPC_MoraggGUID);
|
||||
if (pBoss)
|
||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove1);
|
||||
HandleGameObject(DATA_MORAGG_CELL, true);
|
||||
break;
|
||||
case BOSS_EREKEM:
|
||||
HandleGameObject(GO_ErekemCellGUID, true);
|
||||
HandleGameObject(GO_ErekemRightGuardCellGUID, true);
|
||||
HandleGameObject(GO_ErekemLeftGuardCellGUID, true);
|
||||
pBoss = instance->GetCreature(NPC_ErekemGUID);
|
||||
if (pBoss)
|
||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove2);
|
||||
if (Creature* pGuard1 = instance->GetCreature(NPC_ErekemGuardGUID[0]))
|
||||
HandleGameObject(DATA_EREKEM_CELL, true);
|
||||
HandleGameObject(DATA_EREKEM_GUARD_2_CELL, true);
|
||||
HandleGameObject(DATA_EREKEM_GUARD_1_CELL, true);
|
||||
if (Creature* guard1 = instance->GetCreature(_erekemGuardGuid[0]))
|
||||
{
|
||||
pGuard1->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
pGuard1->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
pGuard1->SetImmuneToNPC(false);
|
||||
pGuard1->GetMotionMaster()->MovePoint(0, BossStartMove21);
|
||||
guard1->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
guard1->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
guard1->SetImmuneToNPC(false);
|
||||
guard1->GetMotionMaster()->MovePoint(0, BossStartMove21);
|
||||
}
|
||||
if (Creature* pGuard2 = instance->GetCreature(NPC_ErekemGuardGUID[1]))
|
||||
if (Creature* guard2 = instance->GetCreature(_erekemGuardGuid[1]))
|
||||
{
|
||||
pGuard2->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
pGuard2->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
pGuard2->SetImmuneToNPC(false);
|
||||
pGuard2->GetMotionMaster()->MovePoint(0, BossStartMove22);
|
||||
guard2->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
guard2->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
guard2->SetImmuneToNPC(false);
|
||||
guard2->GetMotionMaster()->MovePoint(0, BossStartMove22);
|
||||
}
|
||||
break;
|
||||
case BOSS_ICHORON:
|
||||
HandleGameObject(GO_IchoronCellGUID, true);
|
||||
pBoss = instance->GetCreature(NPC_IchoronGUID);
|
||||
if (pBoss)
|
||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove3);
|
||||
HandleGameObject(DATA_ICHORON_CELL, true);
|
||||
break;
|
||||
case BOSS_LAVANTHOR:
|
||||
HandleGameObject(GO_LavanthorCellGUID, true);
|
||||
pBoss = instance->GetCreature(NPC_LavanthorGUID);
|
||||
if (pBoss)
|
||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove4);
|
||||
HandleGameObject(DATA_LAVANTHOR_CELL, true);
|
||||
break;
|
||||
case BOSS_XEVOZZ:
|
||||
HandleGameObject(GO_XevozzCellGUID, true);
|
||||
pBoss = instance->GetCreature(NPC_XevozzGUID);
|
||||
if (pBoss)
|
||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove5);
|
||||
HandleGameObject(DATA_XEVOZZ_CELL, true);
|
||||
break;
|
||||
case BOSS_ZURAMAT:
|
||||
HandleGameObject(GO_ZuramatCellGUID, true);
|
||||
pBoss = instance->GetCreature(NPC_ZuramatGUID);
|
||||
if (pBoss)
|
||||
pBoss->GetMotionMaster()->MovePoint(0, BossStartMove6);
|
||||
HandleGameObject(DATA_ZURAMAT_CELL, true);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pBoss)
|
||||
static Position const BossStartPositions[] =
|
||||
{
|
||||
pBoss->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
pBoss->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
pBoss->SetImmuneToNPC(false);
|
||||
pBoss->SetReactState(REACT_AGGRESSIVE);
|
||||
if ((WaveCount == 6 && m_auiEncounter[0] == DONE) || (WaveCount == 12 && m_auiEncounter[1] == DONE))
|
||||
pBoss->SetLootMode(0);
|
||||
BossStartMove1, // BOSS_MORAGG
|
||||
BossStartMove2, // BOSS_EREKEM
|
||||
BossStartMove3, // BOSS_ICHORON
|
||||
BossStartMove4, // BOSS_LAVANTHOR
|
||||
BossStartMove5, // BOSS_XEVOZZ
|
||||
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
|
||||
{
|
||||
events.Update(diff);
|
||||
switch (events.ExecuteEvent())
|
||||
_events.Update(diff);
|
||||
switch (_events.ExecuteEvent())
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case EVENT_CHECK_PLAYERS:
|
||||
{
|
||||
if (DoNeedCleanup(false))
|
||||
InstanceCleanup();
|
||||
events.Repeat(5s);
|
||||
}
|
||||
if (DoNeedCleanup(false))
|
||||
InstanceCleanup();
|
||||
_events.Repeat(5s);
|
||||
break;
|
||||
case EVENT_GUARDS_FALL_BACK:
|
||||
{
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
if (Creature* c = instance->GetCreature(NPC_GuardGUID[i]))
|
||||
{
|
||||
c->SetReactState(REACT_PASSIVE);
|
||||
c->CombatStop();
|
||||
c->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
c->GetMotionMaster()->MovePoint(0, guardMovePosition);
|
||||
}
|
||||
events.RescheduleEvent(EVENT_GUARDS_DISAPPEAR, 5s);
|
||||
}
|
||||
for (ObjectGuid const& guid : _guardGuid)
|
||||
if (Creature* guard = instance->GetCreature(guid))
|
||||
{
|
||||
guard->SetReactState(REACT_PASSIVE);
|
||||
guard->CombatStop();
|
||||
guard->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
guard->GetMotionMaster()->MovePoint(0, guardMovePosition);
|
||||
}
|
||||
_events.RescheduleEvent(EVENT_GUARDS_DISAPPEAR, 5s);
|
||||
break;
|
||||
case EVENT_GUARDS_DISAPPEAR:
|
||||
{
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
if (Creature* c = instance->GetCreature(NPC_GuardGUID[i]))
|
||||
c->SetVisible(false);
|
||||
events.RescheduleEvent(EVENT_SINCLARI_FALL_BACK, 2s);
|
||||
}
|
||||
for (ObjectGuid const& guid : _guardGuid)
|
||||
if (Creature* guard = instance->GetCreature(guid))
|
||||
guard->SetVisible(false);
|
||||
_events.RescheduleEvent(EVENT_SINCLARI_FALL_BACK, 2s);
|
||||
break;
|
||||
case EVENT_SINCLARI_FALL_BACK:
|
||||
if (Creature* sinclari = GetCreature(DATA_SINCLARI))
|
||||
{
|
||||
if (Creature* c = instance->GetCreature(NPC_SinclariGUID))
|
||||
{
|
||||
c->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
c->GetMotionMaster()->MovePoint(0, sinclariOutsidePosition);
|
||||
}
|
||||
SetData(DATA_ACTIVATE_DEFENSE_SYSTEM, 0);
|
||||
events.RescheduleEvent(EVENT_START_ENCOUNTER, 4s);
|
||||
sinclari->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
sinclari->GetMotionMaster()->MovePoint(0, sinclariOutsidePosition);
|
||||
}
|
||||
SetData(DATA_ACTIVATE_DEFENSE_SYSTEM, 0);
|
||||
_events.RescheduleEvent(EVENT_START_ENCOUNTER, 4s);
|
||||
break;
|
||||
case EVENT_START_ENCOUNTER:
|
||||
if (Creature* sinclari = GetCreature(DATA_SINCLARI))
|
||||
{
|
||||
if (Creature* c = instance->GetCreature(NPC_SinclariGUID))
|
||||
{
|
||||
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);
|
||||
sinclari->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
sinclari->AI()->Talk(SAY_SINCLARI_DOOR_LOCK);
|
||||
}
|
||||
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;
|
||||
case EVENT_SUMMON_PORTAL:
|
||||
++WaveCount;
|
||||
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_WAVE_COUNT, (uint32)WaveCount);
|
||||
++_waveCount;
|
||||
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_WAVE_COUNT, (uint32)_waveCount);
|
||||
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)
|
||||
c->SummonCreature(NPC_TELEPORTATION_PORTAL, PortalLocations[GetData(DATA_PORTAL_LOCATION)], TEMPSUMMON_CORPSE_DESPAWN);
|
||||
else if (WaveCount == 6 || WaveCount == 12) // first or second boss
|
||||
if (_waveCount % 6 != 0)
|
||||
sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, PortalLocations[GetData(DATA_PORTAL_LOCATION)], TEMPSUMMON_CORPSE_DESPAWN);
|
||||
else if (_waveCount == 6 || _waveCount == 12)
|
||||
{
|
||||
if (!uiFirstBoss || !uiSecondBoss)
|
||||
if (!GetPersistentData(PERSISTENT_DATA_FIRST_BOSS) || !GetPersistentData(PERSISTENT_DATA_SECOND_BOSS))
|
||||
{
|
||||
uiFirstBoss = urand(1, 6);
|
||||
do { uiSecondBoss = urand(1, 6); }
|
||||
while (uiFirstBoss == uiSecondBoss);
|
||||
SaveToDB();
|
||||
uint32 firstBoss = urand(BOSS_MORAGG, BOSS_ZURAMAT);
|
||||
uint32 secondBoss;
|
||||
do { secondBoss = urand(BOSS_MORAGG, BOSS_ZURAMAT); }
|
||||
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->AI()->Talk(CYANIGOSA_SAY_SPAWN);
|
||||
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;
|
||||
case EVENT_CYANIGOSSA_TRANSFORM:
|
||||
if (Creature* c = instance->GetCreature(NPC_CyanigosaGUID))
|
||||
case EVENT_CYANIGOSA_TRANSFORM:
|
||||
if (Creature* cyanigosa = GetCreature(DATA_CYANIGOSA))
|
||||
{
|
||||
c->RemoveAurasDueToSpell(SPELL_CYANIGOSA_BLUE_AURA);
|
||||
c->CastSpell(c, SPELL_CYANIGOSA_TRANSFORM, 0);
|
||||
events.RescheduleEvent(EVENT_CYANIGOSA_ATTACK, 2500ms);
|
||||
cyanigosa->RemoveAurasDueToSpell(SPELL_CYANIGOSA_BLUE_AURA);
|
||||
cyanigosa->CastSpell(cyanigosa, SPELL_CYANIGOSA_TRANSFORM, 0);
|
||||
_events.RescheduleEvent(EVENT_CYANIGOSA_ATTACK, 2500ms);
|
||||
}
|
||||
break;
|
||||
case EVENT_CYANIGOSA_ATTACK:
|
||||
if (Creature* c = instance->GetCreature(NPC_CyanigosaGUID))
|
||||
if (Creature* cyanigosa = GetCreature(DATA_CYANIGOSA))
|
||||
{
|
||||
c->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
c->SetImmuneToNPC(false);
|
||||
cyanigosa->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
cyanigosa->SetImmuneToNPC(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -531,121 +450,118 @@ public:
|
|||
if (DoNeedCleanup(plr->IsAlive()))
|
||||
InstanceCleanup();
|
||||
|
||||
if (EncounterStatus == IN_PROGRESS)
|
||||
if (_encounterStatus == IN_PROGRESS)
|
||||
{
|
||||
plr->SendUpdateWorldState(WORLD_STATE_VIOLET_HOLD_SHOW, 1);
|
||||
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_PRISON_STATE, (uint32)_gateHealth);
|
||||
plr->SendUpdateWorldState(WORLD_STATE_VIOLET_HOLD_WAVE_COUNT, (uint32)_waveCount);
|
||||
}
|
||||
else
|
||||
plr->SendUpdateWorldState(WORLD_STATE_VIOLET_HOLD_SHOW, 0);
|
||||
|
||||
events.RescheduleEvent(EVENT_CHECK_PLAYERS, 5s);
|
||||
_events.RescheduleEvent(EVENT_CHECK_PLAYERS, 5s);
|
||||
}
|
||||
|
||||
bool DoNeedCleanup(bool enter)
|
||||
{
|
||||
uint8 aliveCount = 0;
|
||||
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;
|
||||
|
||||
uint32 aliveCount = instance->GetPlayersCountExceptGMs(true);
|
||||
bool need = enter ? aliveCount <= 1 : aliveCount == 0;
|
||||
if (!need && CLEANED)
|
||||
CLEANED = false;
|
||||
if (!need && _cleaned)
|
||||
_cleaned = false;
|
||||
return need;
|
||||
}
|
||||
|
||||
void InstanceCleanup()
|
||||
{
|
||||
if (CLEANED)
|
||||
if (_cleaned)
|
||||
return;
|
||||
CLEANED = true;
|
||||
_cleaned = true;
|
||||
|
||||
// reset defense crystals
|
||||
for (ObjectGuid const& guid : GO_ActivationCrystalGUID)
|
||||
for (ObjectGuid const& guid : _activationCrystalGuidList)
|
||||
if (GameObject* go = instance->GetGameObject(guid))
|
||||
{
|
||||
HandleGameObject(ObjectGuid::Empty, false, go); // not used yet
|
||||
go->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE); // not useable at the beginning
|
||||
HandleGameObject(ObjectGuid::Empty, false, go);
|
||||
go->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
|
||||
// reset positions of Sinclari and Guards
|
||||
if (Creature* c = instance->GetCreature(NPC_SinclariGUID))
|
||||
if (Creature* sinclari = GetCreature(DATA_SINCLARI))
|
||||
{
|
||||
c->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
c->DespawnOrUnsummon();
|
||||
c->SetRespawnTime(3);
|
||||
sinclari->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
sinclari->DespawnOrUnsummon();
|
||||
sinclari->SetRespawnTime(3);
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
if (Creature* c = instance->GetCreature(NPC_GuardGUID[i]))
|
||||
for (ObjectGuid const& guid : _guardGuid)
|
||||
if (Creature* guard = instance->GetCreature(guid))
|
||||
{
|
||||
c->DespawnOrUnsummon();
|
||||
c->SetRespawnTime(3);
|
||||
if (m_auiEncounter[MAX_ENCOUNTER - 1] == DONE)
|
||||
c->SetVisible(false);
|
||||
else
|
||||
c->SetVisible(true);
|
||||
c->SetReactState(REACT_AGGRESSIVE);
|
||||
guard->DespawnOrUnsummon();
|
||||
guard->SetRespawnTime(3);
|
||||
guard->SetVisible(GetBossState(DATA_CYANIGOSA) != DONE);
|
||||
guard->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
|
||||
// remove portal if any
|
||||
if (Creature* c = instance->GetCreature(NPC_PortalGUID))
|
||||
c->DespawnOrUnsummon();
|
||||
NPC_PortalGUID.Clear();
|
||||
if (Creature* portal = GetCreature(DATA_TELEPORTATION_PORTAL))
|
||||
portal->DespawnOrUnsummon();
|
||||
|
||||
// remove trash
|
||||
for (ObjectGuid const& guid : trashMobs)
|
||||
if (Creature* c = instance->GetCreature(guid))
|
||||
c->DespawnOrUnsummon();
|
||||
for (ObjectGuid const& guid : _trashMobs)
|
||||
if (Creature* trash = instance->GetCreature(guid))
|
||||
trash->DespawnOrUnsummon();
|
||||
|
||||
trashMobs.clear();
|
||||
_trashMobs.clear();
|
||||
|
||||
// clear door seal damaging auras:
|
||||
if (Creature* c = instance->GetCreature(NPC_DoorSealGUID))
|
||||
c->RemoveAllAuras();
|
||||
if (Creature* doorSeal = GetCreature(DATA_DOOR_SEAL))
|
||||
doorSeal->RemoveAllAuras();
|
||||
|
||||
// open main gate
|
||||
HandleGameObject(GO_MainGateGUID, true);
|
||||
HandleGameObject(DATA_MAIN_DOOR, true);
|
||||
|
||||
if (m_auiEncounter[MAX_ENCOUNTER - 1] != DONE) // instance not finished
|
||||
if (GetBossState(DATA_CYANIGOSA) != DONE)
|
||||
{
|
||||
// close all cells
|
||||
HandleGameObject(GO_MoraggCellGUID, false);
|
||||
HandleGameObject(GO_ErekemCellGUID, false);
|
||||
HandleGameObject(GO_ErekemRightGuardCellGUID, false);
|
||||
HandleGameObject(GO_ErekemLeftGuardCellGUID, false);
|
||||
HandleGameObject(GO_IchoronCellGUID, false);
|
||||
HandleGameObject(GO_LavanthorCellGUID, false);
|
||||
HandleGameObject(GO_XevozzCellGUID, false);
|
||||
HandleGameObject(GO_ZuramatCellGUID, false);
|
||||
HandleGameObject(DATA_MORAGG_CELL, false);
|
||||
HandleGameObject(DATA_EREKEM_CELL, false);
|
||||
HandleGameObject(DATA_EREKEM_GUARD_2_CELL, false);
|
||||
HandleGameObject(DATA_EREKEM_GUARD_1_CELL, false);
|
||||
HandleGameObject(DATA_ICHORON_CELL, false);
|
||||
HandleGameObject(DATA_LAVANTHOR_CELL, false);
|
||||
HandleGameObject(DATA_XEVOZZ_CELL, false);
|
||||
HandleGameObject(DATA_ZURAMAT_CELL, false);
|
||||
|
||||
// respawn bosses
|
||||
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* 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); }
|
||||
if (Creature* c = instance->GetCreature(NPC_ErekemGuardGUID[1])) { c->DespawnOrUnsummon(); c->SetRespawnTime(3); c->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); c->SetImmuneToNPC(true); }
|
||||
if (Creature* c = instance->GetCreature(NPC_IchoronGUID)) { c->DespawnOrUnsummon(); c->SetRespawnTime(3); c->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); c->SetImmuneToNPC(true); }
|
||||
if (Creature* c = instance->GetCreature(NPC_LavanthorGUID)) { c->DespawnOrUnsummon(); c->SetRespawnTime(3); c->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); c->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(); }
|
||||
for (uint32 id = BOSS_MORAGG; id <= BOSS_ZURAMAT; ++id)
|
||||
{
|
||||
if (Creature* boss = GetCreature(id))
|
||||
{
|
||||
boss->DespawnOrUnsummon();
|
||||
boss->SetRespawnTime(3);
|
||||
boss->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
boss->SetImmuneToNPC(true);
|
||||
}
|
||||
}
|
||||
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);
|
||||
EncounterStatus = NOT_STARTED;
|
||||
GateHealth = 100;
|
||||
WaveCount = 0;
|
||||
bDefensesUsed = false;
|
||||
if (m_auiEncounter[MAX_ENCOUNTER - 1] == DONE)
|
||||
EncounterStatus = DONE;
|
||||
events.Reset();
|
||||
events.RescheduleEvent(EVENT_CHECK_PLAYERS, 5s);
|
||||
_encounterStatus = NOT_STARTED;
|
||||
_gateHealth = 100;
|
||||
_waveCount = 0;
|
||||
_defensesUsed = false;
|
||||
if (GetBossState(DATA_CYANIGOSA) == DONE)
|
||||
_encounterStatus = DONE;
|
||||
_events.Reset();
|
||||
_events.RescheduleEvent(EVENT_CHECK_PLAYERS, 5s);
|
||||
}
|
||||
|
||||
bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/) override
|
||||
|
|
@ -653,35 +569,31 @@ public:
|
|||
switch (criteria_id)
|
||||
{
|
||||
case CRITERIA_DEFENSELESS:
|
||||
return GateHealth == 100 && !bDefensesUsed;
|
||||
return _gateHealth == 100 && !_defensesUsed;
|
||||
case CRITERIA_A_VOID_DANCE:
|
||||
case CRITERIA_DEHYDRATION:
|
||||
return bAchiev;
|
||||
return _achievementCompleted;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ReadSaveDataMore(std::istringstream& data) override
|
||||
{
|
||||
EncounterStatus = NOT_STARTED;
|
||||
CLEANED = false;
|
||||
events.Reset();
|
||||
events.RescheduleEvent(EVENT_CHECK_PLAYERS, 0ms);
|
||||
private:
|
||||
bool _cleaned{ false };
|
||||
uint8 _encounterStatus{ NOT_STARTED };
|
||||
EventMap _events;
|
||||
uint8 _gateHealth{ 100 };
|
||||
uint8 _waveCount{ 0 };
|
||||
uint8 _portalLocation{ 0 };
|
||||
bool _achievementCompleted{ false };
|
||||
bool _defensesUsed{ false };
|
||||
|
||||
data >> m_auiEncounter[0];
|
||||
data >> m_auiEncounter[1];
|
||||
data >> m_auiEncounter[2];
|
||||
data >> uiFirstBoss;
|
||||
}
|
||||
GuidVector _activationCrystalGuidList;
|
||||
|
||||
void WriteSaveDataMore(std::ostringstream& data) override
|
||||
{
|
||||
data << m_auiEncounter[0] << ' '
|
||||
<< m_auiEncounter[1] << ' '
|
||||
<< m_auiEncounter[2] << ' '
|
||||
<< uiFirstBoss << ' '
|
||||
<< uiSecondBoss << ' ';
|
||||
}
|
||||
// Multi-instance creature tracking (can't use ObjectData)
|
||||
ObjectGuid _guardGuid[4];
|
||||
ObjectGuid _erekemGuardGuid[2];
|
||||
|
||||
GuidSet _trashMobs;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -18,15 +18,57 @@
|
|||
#ifndef DEF_VIOLET_HOLD_H
|
||||
#define DEF_VIOLET_HOLD_H
|
||||
|
||||
#define MAX_ENCOUNTER 3
|
||||
|
||||
#include "CreatureAIImpl.h"
|
||||
|
||||
#define DataHeader "VIO"
|
||||
|
||||
#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_DEFENSE_SYSTEM = 30837,
|
||||
|
|
@ -63,7 +105,7 @@ enum Creatures
|
|||
NPC_AZURE_STALKER = 32191,
|
||||
};
|
||||
|
||||
enum GameObjects
|
||||
enum VHGameObjects
|
||||
{
|
||||
GO_MAIN_DOOR = 191723,
|
||||
GO_XEVOZZ_DOOR = 191556,
|
||||
|
|
@ -78,19 +120,25 @@ enum GameObjects
|
|||
GO_ACTIVATION_CRYSTAL = 193611,
|
||||
};
|
||||
|
||||
enum Bosses
|
||||
enum VHBosses
|
||||
{
|
||||
BOSS_NONE,
|
||||
BOSS_MORAGG,
|
||||
// Encounter slot IDs (used by SetBossState/GetBossState)
|
||||
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_ICHORON,
|
||||
BOSS_LAVANTHOR,
|
||||
BOSS_XEVOZZ,
|
||||
BOSS_ZURAMAT,
|
||||
BOSS_CYANIGOSA
|
||||
MAX_BOSS
|
||||
};
|
||||
|
||||
enum Spells
|
||||
enum VHSpells
|
||||
{
|
||||
SPELL_CONTROL_CRYSTAL_ACTIVATION = 57804,
|
||||
SPELL_DEFENSE_SYSTEM_SPAWN_EFFECT = 57886,
|
||||
|
|
@ -104,7 +152,7 @@ enum Spells
|
|||
SPELL_CYANIGOSA_BLUE_AURA = 45870
|
||||
};
|
||||
|
||||
enum Events
|
||||
enum VHInstanceEvents
|
||||
{
|
||||
EVENT_CHECK_PLAYERS = 1,
|
||||
EVENT_GUARDS_FALL_BACK,
|
||||
|
|
@ -112,7 +160,7 @@ enum Events
|
|||
EVENT_SINCLARI_FALL_BACK,
|
||||
EVENT_START_ENCOUNTER,
|
||||
EVENT_SUMMON_PORTAL,
|
||||
EVENT_CYANIGOSSA_TRANSFORM,
|
||||
EVENT_CYANIGOSA_TRANSFORM,
|
||||
EVENT_CYANIGOSA_ATTACK,
|
||||
|
||||
// Event defense system
|
||||
|
|
@ -120,32 +168,7 @@ enum Events
|
|||
EVENT_ARCANE_LIGHTNING_INSTAKILL
|
||||
};
|
||||
|
||||
enum Data
|
||||
{
|
||||
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
|
||||
enum VHAchievCriteria
|
||||
{
|
||||
CRITERIA_DEFENSELESS = 6803,
|
||||
CRITERIA_A_VOID_DANCE = 7587,
|
||||
|
|
@ -308,4 +331,6 @@ inline AI* GetVioletHoldAI(T* obj)
|
|||
return GetInstanceAI<AI>(obj, VioletHoldScriptName);
|
||||
}
|
||||
|
||||
#define RegisterVioletHoldCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetVioletHoldAI)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue