refactor(Core/Scripts): Move AQ scripts to new scripting system (#12623)
This commit is contained in:
@@ -68,244 +68,222 @@ const Position LarvaPos[2] =
|
|||||||
{ -9701.6005f, 1566.9993f, 24.118f, 0.0f }
|
{ -9701.6005f, 1566.9993f, 24.118f, 0.0f }
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_ayamiss : public CreatureScript
|
struct boss_ayamiss : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_ayamiss(Creature* creature) : BossAI(creature, DATA_AYAMISS) {}
|
||||||
boss_ayamiss() : CreatureScript("boss_ayamiss") { }
|
|
||||||
|
|
||||||
struct boss_ayamissAI : public BossAI
|
void Reset() override
|
||||||
{
|
{
|
||||||
boss_ayamissAI(Creature* creature) : BossAI(creature, DATA_AYAMISS) {}
|
BossAI::Reset();
|
||||||
|
_phase = PHASE_AIR;
|
||||||
void Reset() override
|
_enraged = false;
|
||||||
{
|
SetCombatMovement(false);
|
||||||
_Reset();
|
|
||||||
_phase = PHASE_AIR;
|
|
||||||
_enraged = false;
|
|
||||||
SetCombatMovement(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustSummoned(Creature* who) override
|
|
||||||
{
|
|
||||||
switch (who->GetEntry())
|
|
||||||
{
|
|
||||||
case NPC_SWARMER:
|
|
||||||
_swarmers.push_back(who->GetGUID());
|
|
||||||
break;
|
|
||||||
case NPC_LARVA:
|
|
||||||
who->GetMotionMaster()->MovePoint(POINT_PARALYZE, AltarPos);
|
|
||||||
break;
|
|
||||||
case NPC_HORNET:
|
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
|
|
||||||
{
|
|
||||||
who->AI()->AttackStart(target);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
summons.Summon(who);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovementInform(uint32 type, uint32 id) override
|
|
||||||
{
|
|
||||||
if (type == POINT_MOTION_TYPE)
|
|
||||||
{
|
|
||||||
switch (id)
|
|
||||||
{
|
|
||||||
case POINT_AIR:
|
|
||||||
me->AddUnitState(UNIT_STATE_ROOT);
|
|
||||||
break;
|
|
||||||
case POINT_GROUND:
|
|
||||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnterEvadeMode(EvadeReason why) override
|
|
||||||
{
|
|
||||||
me->ClearUnitState(UNIT_STATE_ROOT);
|
|
||||||
BossAI::EnterEvadeMode(why);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnterCombat(Unit* attacker) override
|
|
||||||
{
|
|
||||||
BossAI::EnterCombat(attacker);
|
|
||||||
events.ScheduleEvent(EVENT_STINGER_SPRAY, urand(20000, 30000));
|
|
||||||
events.ScheduleEvent(EVENT_POISON_STINGER, 5000);
|
|
||||||
events.ScheduleEvent(EVENT_SUMMON_SWARMER, 5000);
|
|
||||||
events.ScheduleEvent(EVENT_SWARMER_ATTACK, 60000);
|
|
||||||
events.ScheduleEvent(EVENT_PARALYZE, 15000);
|
|
||||||
me->SetCanFly(true);
|
|
||||||
me->SetDisableGravity(true);
|
|
||||||
me->GetMotionMaster()->MovePoint(POINT_AIR, AyamissAirPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
|
|
||||||
{
|
|
||||||
if (_phase == PHASE_AIR && me->GetHealthPct() < 70.0f)
|
|
||||||
{
|
|
||||||
_phase = PHASE_GROUND;
|
|
||||||
SetCombatMovement(true);
|
|
||||||
me->ClearUnitState(UNIT_STATE_ROOT);
|
|
||||||
me->SetCanFly(false);
|
|
||||||
me->SetDisableGravity(false);
|
|
||||||
if (Unit* victim = me->GetVictim())
|
|
||||||
{
|
|
||||||
Position victimPos = victim->GetPosition();
|
|
||||||
me->GetMotionMaster()->MovePoint(POINT_GROUND, victimPos);
|
|
||||||
}
|
|
||||||
events.ScheduleEvent(EVENT_LASH, urand(5000, 8000));
|
|
||||||
events.CancelEvent(EVENT_POISON_STINGER);
|
|
||||||
DoResetThreat();
|
|
||||||
}
|
|
||||||
if (!_enraged && me->GetHealthPct() < 20.0f)
|
|
||||||
{
|
|
||||||
DoCastSelf(SPELL_FRENZY);
|
|
||||||
Talk(EMOTE_FRENZY);
|
|
||||||
_enraged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
|
||||||
if (!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
events.Update(diff);
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
switch (eventId)
|
|
||||||
{
|
|
||||||
case EVENT_STINGER_SPRAY:
|
|
||||||
DoCastSelf(SPELL_STINGER_SPRAY);
|
|
||||||
events.ScheduleEvent(EVENT_STINGER_SPRAY, urand(15000, 20000));
|
|
||||||
break;
|
|
||||||
case EVENT_POISON_STINGER:
|
|
||||||
DoCastVictim(SPELL_POISON_STINGER);
|
|
||||||
events.ScheduleEvent(EVENT_POISON_STINGER, urand(2000, 3000));
|
|
||||||
break;
|
|
||||||
case EVENT_PARALYZE:
|
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0, true))
|
|
||||||
{
|
|
||||||
DoCast(target, SPELL_PARALYZE);
|
|
||||||
instance->SetGuidData(DATA_PARALYZED, target->GetGUID());
|
|
||||||
uint8 Index = urand(0, 1);
|
|
||||||
me->SummonCreature(NPC_LARVA, LarvaPos[Index], TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
|
|
||||||
}
|
|
||||||
events.ScheduleEvent(EVENT_PARALYZE, 15000);
|
|
||||||
break;
|
|
||||||
case EVENT_SWARMER_ATTACK:
|
|
||||||
for (ObjectGuid const& guid : _swarmers)
|
|
||||||
{
|
|
||||||
if (Creature* swarmer = me->GetMap()->GetCreature(guid))
|
|
||||||
{
|
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
|
|
||||||
{
|
|
||||||
swarmer->AI()->AttackStart(target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_swarmers.clear();
|
|
||||||
events.ScheduleEvent(EVENT_SWARMER_ATTACK, 60000);
|
|
||||||
break;
|
|
||||||
case EVENT_SUMMON_SWARMER:
|
|
||||||
{
|
|
||||||
Position Pos = me->GetRandomPoint(SwarmerPos, 80.0f);
|
|
||||||
me->SummonCreature(NPC_SWARMER, Pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000);
|
|
||||||
events.ScheduleEvent(EVENT_SUMMON_SWARMER, 5000);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EVENT_LASH:
|
|
||||||
DoCastVictim(SPELL_LASH);
|
|
||||||
events.ScheduleEvent(EVENT_LASH, urand(8000, 15000));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
GuidList _swarmers;
|
|
||||||
uint8 _phase;
|
|
||||||
bool _enraged;
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
|
||||||
return GetRuinsOfAhnQirajAI<boss_ayamissAI>(creature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JustSummoned(Creature* who) override
|
||||||
|
{
|
||||||
|
switch (who->GetEntry())
|
||||||
|
{
|
||||||
|
case NPC_SWARMER:
|
||||||
|
_swarmers.push_back(who->GetGUID());
|
||||||
|
break;
|
||||||
|
case NPC_LARVA:
|
||||||
|
who->GetMotionMaster()->MovePoint(POINT_PARALYZE, AltarPos);
|
||||||
|
break;
|
||||||
|
case NPC_HORNET:
|
||||||
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
|
||||||
|
{
|
||||||
|
who->AI()->AttackStart(target);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
summons.Summon(who);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementInform(uint32 type, uint32 id) override
|
||||||
|
{
|
||||||
|
if (type == POINT_MOTION_TYPE)
|
||||||
|
{
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case POINT_AIR:
|
||||||
|
me->AddUnitState(UNIT_STATE_ROOT);
|
||||||
|
break;
|
||||||
|
case POINT_GROUND:
|
||||||
|
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnterEvadeMode(EvadeReason why) override
|
||||||
|
{
|
||||||
|
me->ClearUnitState(UNIT_STATE_ROOT);
|
||||||
|
BossAI::EnterEvadeMode(why);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnterCombat(Unit* attacker) override
|
||||||
|
{
|
||||||
|
BossAI::EnterCombat(attacker);
|
||||||
|
events.ScheduleEvent(EVENT_STINGER_SPRAY, 20s, 30s);
|
||||||
|
events.ScheduleEvent(EVENT_POISON_STINGER, 5s);
|
||||||
|
events.ScheduleEvent(EVENT_SUMMON_SWARMER, 5s);
|
||||||
|
events.ScheduleEvent(EVENT_SWARMER_ATTACK, 60s);
|
||||||
|
events.ScheduleEvent(EVENT_PARALYZE, 15s);
|
||||||
|
me->SetCanFly(true);
|
||||||
|
me->SetDisableGravity(true);
|
||||||
|
me->GetMotionMaster()->MovePoint(POINT_AIR, AyamissAirPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
|
||||||
|
{
|
||||||
|
if (_phase == PHASE_AIR && me->GetHealthPct() < 70.0f)
|
||||||
|
{
|
||||||
|
_phase = PHASE_GROUND;
|
||||||
|
SetCombatMovement(true);
|
||||||
|
me->ClearUnitState(UNIT_STATE_ROOT);
|
||||||
|
me->SetCanFly(false);
|
||||||
|
me->SetDisableGravity(false);
|
||||||
|
if (Unit* victim = me->GetVictim())
|
||||||
|
{
|
||||||
|
Position victimPos = victim->GetPosition();
|
||||||
|
me->GetMotionMaster()->MovePoint(POINT_GROUND, victimPos);
|
||||||
|
}
|
||||||
|
events.ScheduleEvent(EVENT_LASH, 5s, 8s);
|
||||||
|
events.CancelEvent(EVENT_POISON_STINGER);
|
||||||
|
DoResetThreat();
|
||||||
|
}
|
||||||
|
if (!_enraged && me->GetHealthPct() < 20.0f)
|
||||||
|
{
|
||||||
|
DoCastSelf(SPELL_FRENZY);
|
||||||
|
Talk(EMOTE_FRENZY);
|
||||||
|
_enraged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
if (!UpdateVictim())
|
||||||
|
return;
|
||||||
|
|
||||||
|
events.Update(diff);
|
||||||
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
|
{
|
||||||
|
switch (eventId)
|
||||||
|
{
|
||||||
|
case EVENT_STINGER_SPRAY:
|
||||||
|
DoCastSelf(SPELL_STINGER_SPRAY);
|
||||||
|
events.ScheduleEvent(EVENT_STINGER_SPRAY, 15s, 20s);
|
||||||
|
break;
|
||||||
|
case EVENT_POISON_STINGER:
|
||||||
|
DoCastVictim(SPELL_POISON_STINGER);
|
||||||
|
events.ScheduleEvent(EVENT_POISON_STINGER, 2s, 3s);
|
||||||
|
break;
|
||||||
|
case EVENT_PARALYZE:
|
||||||
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0, true))
|
||||||
|
{
|
||||||
|
DoCast(target, SPELL_PARALYZE);
|
||||||
|
instance->SetGuidData(DATA_PARALYZED, target->GetGUID());
|
||||||
|
uint8 index = urand(0, 1);
|
||||||
|
me->SummonCreature(NPC_LARVA, LarvaPos[index], TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
|
||||||
|
}
|
||||||
|
events.ScheduleEvent(EVENT_PARALYZE, 15s);
|
||||||
|
break;
|
||||||
|
case EVENT_SWARMER_ATTACK:
|
||||||
|
for (ObjectGuid const& guid : _swarmers)
|
||||||
|
{
|
||||||
|
if (Creature* swarmer = me->GetMap()->GetCreature(guid))
|
||||||
|
{
|
||||||
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
|
||||||
|
{
|
||||||
|
swarmer->AI()->AttackStart(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_swarmers.clear();
|
||||||
|
events.ScheduleEvent(EVENT_SWARMER_ATTACK, 60s);
|
||||||
|
break;
|
||||||
|
case EVENT_SUMMON_SWARMER:
|
||||||
|
{
|
||||||
|
Position Pos = me->GetRandomPoint(SwarmerPos, 80.0f);
|
||||||
|
me->SummonCreature(NPC_SWARMER, Pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000);
|
||||||
|
events.ScheduleEvent(EVENT_SUMMON_SWARMER, 5s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EVENT_LASH:
|
||||||
|
DoCastVictim(SPELL_LASH);
|
||||||
|
events.ScheduleEvent(EVENT_LASH, 8s, 15s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
GuidList _swarmers;
|
||||||
|
uint8 _phase;
|
||||||
|
bool _enraged;
|
||||||
};
|
};
|
||||||
|
|
||||||
class npc_hive_zara_larva : public CreatureScript
|
struct npc_hive_zara_larva : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
npc_hive_zara_larva(Creature* creature) : ScriptedAI(creature)
|
||||||
npc_hive_zara_larva() : CreatureScript("npc_hive_zara_larva") { }
|
|
||||||
|
|
||||||
struct npc_hive_zara_larvaAI : public ScriptedAI
|
|
||||||
{
|
{
|
||||||
npc_hive_zara_larvaAI(Creature* creature) : ScriptedAI(creature)
|
_instance = me->GetInstanceScript();
|
||||||
{
|
}
|
||||||
_instance = me->GetInstanceScript();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovementInform(uint32 type, uint32 id) override
|
void MovementInform(uint32 type, uint32 id) override
|
||||||
|
{
|
||||||
|
if (type == POINT_MOTION_TYPE)
|
||||||
{
|
{
|
||||||
if (type == POINT_MOTION_TYPE)
|
if (id == POINT_PARALYZE)
|
||||||
{
|
{
|
||||||
if (id == POINT_PARALYZE)
|
if (Player* target = ObjectAccessor::GetPlayer(*me, _instance->GetGuidData(DATA_PARALYZED)))
|
||||||
{
|
{
|
||||||
if (Player* target = ObjectAccessor::GetPlayer(*me, _instance->GetGuidData(DATA_PARALYZED)))
|
DoCast(target, SPELL_FEED);
|
||||||
{
|
|
||||||
DoCast(target, SPELL_FEED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustSummoned(Creature* summon) override
|
|
||||||
{
|
|
||||||
if (Creature* ayamiss = _instance->GetCreature(DATA_AYAMISS))
|
|
||||||
{
|
|
||||||
ayamiss->AI()->JustSummoned(summon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* who) override
|
|
||||||
|
|
||||||
{
|
|
||||||
if (_instance->GetBossState(DATA_AYAMISS) == IN_PROGRESS)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ScriptedAI::MoveInLineOfSight(who);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AttackStart(Unit* victim) override
|
|
||||||
{
|
|
||||||
if (_instance->GetBossState(DATA_AYAMISS) == IN_PROGRESS)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ScriptedAI::AttackStart(victim);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
|
||||||
if (_instance->GetBossState(DATA_AYAMISS) == IN_PROGRESS)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ScriptedAI::UpdateAI(diff);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
InstanceScript* _instance;
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
|
||||||
return GetRuinsOfAhnQirajAI<npc_hive_zara_larvaAI>(creature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JustSummoned(Creature* summon) override
|
||||||
|
{
|
||||||
|
if (Creature* ayamiss = _instance->GetCreature(DATA_AYAMISS))
|
||||||
|
{
|
||||||
|
ayamiss->AI()->JustSummoned(summon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveInLineOfSight(Unit* who) override
|
||||||
|
|
||||||
|
{
|
||||||
|
if (_instance->GetBossState(DATA_AYAMISS) == IN_PROGRESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ScriptedAI::MoveInLineOfSight(who);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttackStart(Unit* victim) override
|
||||||
|
{
|
||||||
|
if (_instance->GetBossState(DATA_AYAMISS) == IN_PROGRESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ScriptedAI::AttackStart(victim);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
if (_instance->GetBossState(DATA_AYAMISS) == IN_PROGRESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ScriptedAI::UpdateAI(diff);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
InstanceScript* _instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_ayamiss()
|
void AddSC_boss_ayamiss()
|
||||||
{
|
{
|
||||||
new boss_ayamiss();
|
RegisterRuinsOfAhnQirajCreatureAI(boss_ayamiss);
|
||||||
new npc_hive_zara_larva();
|
RegisterRuinsOfAhnQirajCreatureAI(npc_hive_zara_larva);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ struct boss_buru : public BossAI
|
|||||||
|
|
||||||
void EnterCombat(Unit* who) override
|
void EnterCombat(Unit* who) override
|
||||||
{
|
{
|
||||||
_EnterCombat();
|
BossAI::EnterCombat(who);
|
||||||
Talk(EMOTE_TARGET, who);
|
Talk(EMOTE_TARGET, who);
|
||||||
DoCastSelf(SPELL_THORNS);
|
DoCastSelf(SPELL_THORNS);
|
||||||
ManipulateEggs(true);
|
ManipulateEggs(true);
|
||||||
|
|||||||
@@ -66,9 +66,9 @@ struct boss_moam : public BossAI
|
|||||||
{
|
{
|
||||||
BossAI::EnterCombat(who);
|
BossAI::EnterCombat(who);
|
||||||
Talk(EMOTE_AGGRO);
|
Talk(EMOTE_AGGRO);
|
||||||
events.ScheduleEvent(EVENT_STONE_PHASE, 90000);
|
events.ScheduleEvent(EVENT_STONE_PHASE, 90s);
|
||||||
events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 9000);
|
events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 9s);
|
||||||
events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 3000);
|
events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 3s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
void JustDied(Unit* /*killer*/) override
|
||||||
@@ -113,20 +113,20 @@ struct boss_moam : public BossAI
|
|||||||
DoCastAOE(SPELL_SUMMON_MANA_FIENDS);
|
DoCastAOE(SPELL_SUMMON_MANA_FIENDS);
|
||||||
DoCastSelf(SPELL_ENERGIZE);
|
DoCastSelf(SPELL_ENERGIZE);
|
||||||
events.CancelEvent(EVENT_SPELL_DRAIN_MANA);
|
events.CancelEvent(EVENT_SPELL_DRAIN_MANA);
|
||||||
events.ScheduleEvent(EVENT_STONE_PHASE_END, 90000);
|
events.ScheduleEvent(EVENT_STONE_PHASE_END, 90s);
|
||||||
break;
|
break;
|
||||||
case EVENT_STONE_PHASE_END:
|
case EVENT_STONE_PHASE_END:
|
||||||
me->RemoveAurasDueToSpell(SPELL_ENERGIZE);
|
me->RemoveAurasDueToSpell(SPELL_ENERGIZE);
|
||||||
events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, urand(2000, 6000));
|
events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 2s, 6s);
|
||||||
events.ScheduleEvent(EVENT_STONE_PHASE, 90000);
|
events.ScheduleEvent(EVENT_STONE_PHASE, 90s);
|
||||||
break;
|
break;
|
||||||
case EVENT_SPELL_DRAIN_MANA:
|
case EVENT_SPELL_DRAIN_MANA:
|
||||||
DoCastAOE(SPELL_DRAIN_MANA_SERVERSIDE);
|
DoCastAOE(SPELL_DRAIN_MANA_SERVERSIDE);
|
||||||
events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, urand(2000, 6000));
|
events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 2s, 6s);
|
||||||
break;
|
break;
|
||||||
case EVENT_SPELL_TRAMPLE:
|
case EVENT_SPELL_TRAMPLE:
|
||||||
DoCastAOE(SPELL_TRAMPLE);
|
DoCastAOE(SPELL_TRAMPLE);
|
||||||
events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 15000);
|
events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 15s);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -46,71 +46,60 @@ enum Events
|
|||||||
EVENT_CHANGE_AGGRO = 3,
|
EVENT_CHANGE_AGGRO = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_rajaxx : public CreatureScript
|
struct boss_rajaxx : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_rajaxx(Creature* creature) : BossAI(creature, DATA_RAJAXX) { }
|
||||||
boss_rajaxx() : CreatureScript("boss_rajaxx") { }
|
|
||||||
|
|
||||||
struct boss_rajaxxAI : public BossAI
|
void Reset() override
|
||||||
{
|
{
|
||||||
boss_rajaxxAI(Creature* creature) : BossAI(creature, DATA_RAJAXX) { }
|
BossAI::Reset();
|
||||||
|
enraged = false;
|
||||||
void Reset() override
|
|
||||||
{
|
|
||||||
_Reset();
|
|
||||||
enraged = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
|
||||||
{
|
|
||||||
Talk(SAY_DEATH);
|
|
||||||
_JustDied();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnterCombat(Unit* /*victim*/) override
|
|
||||||
{
|
|
||||||
_EnterCombat();
|
|
||||||
events.ScheduleEvent(EVENT_DISARM, 10000);
|
|
||||||
events.ScheduleEvent(EVENT_THUNDERCRASH, 12000);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
|
||||||
if (!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
events.Update(diff);
|
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
switch (eventId)
|
|
||||||
{
|
|
||||||
case EVENT_DISARM:
|
|
||||||
DoCastVictim(SPELL_DISARM);
|
|
||||||
events.ScheduleEvent(EVENT_DISARM, 22000);
|
|
||||||
break;
|
|
||||||
case EVENT_THUNDERCRASH:
|
|
||||||
DoCast(me, SPELL_THUNDERCRASH);
|
|
||||||
events.ScheduleEvent(EVENT_THUNDERCRASH, 21000);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
bool enraged;
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
|
||||||
return GetRuinsOfAhnQirajAI<boss_rajaxxAI>(creature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JustDied(Unit* /*killer*/) override
|
||||||
|
{
|
||||||
|
Talk(SAY_DEATH);
|
||||||
|
_JustDied();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnterCombat(Unit* /*victim*/) override
|
||||||
|
{
|
||||||
|
_EnterCombat();
|
||||||
|
events.ScheduleEvent(EVENT_DISARM, 10s);
|
||||||
|
events.ScheduleEvent(EVENT_THUNDERCRASH, 12s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
if (!UpdateVictim())
|
||||||
|
return;
|
||||||
|
|
||||||
|
events.Update(diff);
|
||||||
|
|
||||||
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
|
{
|
||||||
|
switch (eventId)
|
||||||
|
{
|
||||||
|
case EVENT_DISARM:
|
||||||
|
DoCastVictim(SPELL_DISARM);
|
||||||
|
events.ScheduleEvent(EVENT_DISARM, 22s);
|
||||||
|
break;
|
||||||
|
case EVENT_THUNDERCRASH:
|
||||||
|
DoCastSelf(SPELL_THUNDERCRASH);
|
||||||
|
events.ScheduleEvent(EVENT_THUNDERCRASH, 21s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
bool enraged;
|
||||||
};
|
};
|
||||||
|
|
||||||
class spell_rajaxx_thundercrash : public SpellScript
|
class spell_rajaxx_thundercrash : public SpellScript
|
||||||
@@ -136,6 +125,6 @@ class spell_rajaxx_thundercrash : public SpellScript
|
|||||||
|
|
||||||
void AddSC_boss_rajaxx()
|
void AddSC_boss_rajaxx()
|
||||||
{
|
{
|
||||||
new boss_rajaxx();
|
RegisterRuinsOfAhnQirajCreatureAI(boss_rajaxx);
|
||||||
RegisterSpellScript(spell_rajaxx_thundercrash);
|
RegisterSpellScript(spell_rajaxx_thundercrash);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -454,9 +454,9 @@ class spell_vem_vengeance : public SpellScript
|
|||||||
|
|
||||||
void AddSC_bug_trio()
|
void AddSC_bug_trio()
|
||||||
{
|
{
|
||||||
RegisterCreatureAI(boss_kri);
|
RegisterTempleOfAhnQirajCreatureAI(boss_kri);
|
||||||
RegisterCreatureAI(boss_vem);
|
RegisterTempleOfAhnQirajCreatureAI(boss_vem);
|
||||||
RegisterCreatureAI(boss_yauj);
|
RegisterTempleOfAhnQirajCreatureAI(boss_yauj);
|
||||||
RegisterSpellScript(spell_vem_knockback);
|
RegisterSpellScript(spell_vem_knockback);
|
||||||
RegisterSpellScript(spell_vem_vengeance);
|
RegisterSpellScript(spell_vem_vengeance);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -42,72 +42,68 @@ enum Spells
|
|||||||
SPELL_ENRAGE = 28798
|
SPELL_ENRAGE = 28798
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_fankriss : public CreatureScript
|
struct boss_fankriss : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
boss_fankriss(Creature* creature) : ScriptedAI(creature) { }
|
||||||
boss_fankriss() : CreatureScript("boss_fankriss") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
void SummonSpawn()
|
||||||
{
|
{
|
||||||
return GetTempleOfAhnQirajAI<boss_fankrissAI>(creature);
|
Rand = 10 + (rand() % 10);
|
||||||
}
|
switch (rand() % 2)
|
||||||
|
|
||||||
struct boss_fankrissAI : public ScriptedAI
|
|
||||||
{
|
|
||||||
boss_fankrissAI(Creature* creature) : ScriptedAI(creature) { }
|
|
||||||
|
|
||||||
void SummonSpawn()
|
|
||||||
{
|
{
|
||||||
Rand = 10 + (rand() % 10);
|
case 0:
|
||||||
switch (rand() % 2)
|
RandX = 0.0f - Rand;
|
||||||
{
|
break;
|
||||||
case 0:
|
case 1:
|
||||||
RandX = 0.0f - Rand;
|
RandX = 0.0f + Rand;
|
||||||
break;
|
break;
|
||||||
case 1:
|
|
||||||
RandX = 0.0f + Rand;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rand = 10 + (rand() % 10);
|
|
||||||
switch (rand() % 2)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
RandY = 0.0f - Rand;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
RandY = 0.0f + Rand;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Rand = 0;
|
|
||||||
DoSpawnCreature(15630, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnterCombat(Unit* /*who*/) override
|
Rand = 10 + (rand() % 10);
|
||||||
|
switch (rand() % 2)
|
||||||
{
|
{
|
||||||
_scheduler.CancelAll();
|
case 0:
|
||||||
|
RandY = 0.0f - Rand;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
RandY = 0.0f + Rand;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Rand = 0;
|
||||||
|
DoSpawnCreature(15630, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
|
||||||
|
}
|
||||||
|
|
||||||
_scheduler.Schedule(4s, 8s, [this](TaskContext context) {
|
void EnterCombat(Unit* /*who*/) override
|
||||||
|
{
|
||||||
|
_scheduler.CancelAll();
|
||||||
|
|
||||||
|
_scheduler
|
||||||
|
.Schedule(4s, 8s, [this](TaskContext context)
|
||||||
|
{
|
||||||
DoCastVictim(SPELL_MORTAL_WOUND);
|
DoCastVictim(SPELL_MORTAL_WOUND);
|
||||||
context.Repeat();
|
context.Repeat();
|
||||||
}).Schedule(15s, 45s, [this](TaskContext context) {
|
})
|
||||||
|
.Schedule(15s, 45s, [this](TaskContext context)
|
||||||
|
{
|
||||||
switch (urand(0, 2))
|
switch (urand(0, 2))
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
SummonSpawn();
|
SummonSpawn();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
SummonSpawn();
|
SummonSpawn();
|
||||||
SummonSpawn();
|
SummonSpawn();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
SummonSpawn();
|
SummonSpawn();
|
||||||
SummonSpawn();
|
SummonSpawn();
|
||||||
SummonSpawn();
|
SummonSpawn();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
context.Repeat(30s, 60s);
|
context.Repeat(30s, 60s);
|
||||||
}).Schedule(15s, 45s, [this](TaskContext context) {
|
})
|
||||||
|
.Schedule(15s, 45s, [this](TaskContext context)
|
||||||
|
{
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
|
||||||
{
|
{
|
||||||
DoCast(target, SPELL_ROOT);
|
DoCast(target, SPELL_ROOT);
|
||||||
@@ -142,27 +138,26 @@ public:
|
|||||||
}
|
}
|
||||||
context.Repeat(45s, 60s);
|
context.Repeat(45s, 60s);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
//Return since we have no target
|
//Return since we have no target
|
||||||
if (!UpdateVictim())
|
if (!UpdateVictim())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_scheduler.Update(diff,
|
_scheduler.Update(diff,
|
||||||
std::bind(&ScriptedAI::DoMeleeAttackIfReady, this));
|
std::bind(&ScriptedAI::DoMeleeAttackIfReady, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TaskScheduler _scheduler;
|
TaskScheduler _scheduler;
|
||||||
int Rand;
|
int Rand;
|
||||||
float RandX;
|
float RandX;
|
||||||
float RandY;
|
float RandY;
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_fankriss()
|
void AddSC_boss_fankriss()
|
||||||
{
|
{
|
||||||
new boss_fankriss();
|
RegisterTempleOfAhnQirajCreatureAI(boss_fankriss);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,115 +41,104 @@ enum Huhuran
|
|||||||
SPELL_WYVERN_STING_DAMAGE = 26233
|
SPELL_WYVERN_STING_DAMAGE = 26233
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_huhuran : public CreatureScript
|
struct boss_huhuran : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
boss_huhuran(Creature* creature) : ScriptedAI(creature) { }
|
||||||
boss_huhuran() : CreatureScript("boss_huhuran") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
uint32 Frenzy_Timer;
|
||||||
|
uint32 Wyvern_Timer;
|
||||||
|
uint32 Spit_Timer;
|
||||||
|
uint32 PoisonBolt_Timer;
|
||||||
|
uint32 NoxiousPoison_Timer;
|
||||||
|
uint32 FrenzyBack_Timer;
|
||||||
|
|
||||||
|
bool Frenzy;
|
||||||
|
bool Berserk;
|
||||||
|
|
||||||
|
void Reset() override
|
||||||
{
|
{
|
||||||
return GetTempleOfAhnQirajAI<boss_huhuranAI>(creature);
|
Frenzy_Timer = urand(25000, 35000);
|
||||||
|
Wyvern_Timer = urand(18000, 28000);
|
||||||
|
Spit_Timer = 8000;
|
||||||
|
PoisonBolt_Timer = 4000;
|
||||||
|
NoxiousPoison_Timer = urand(10000, 20000);
|
||||||
|
FrenzyBack_Timer = 15000;
|
||||||
|
|
||||||
|
Frenzy = false;
|
||||||
|
Berserk = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct boss_huhuranAI : public ScriptedAI
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
boss_huhuranAI(Creature* creature) : ScriptedAI(creature) { }
|
//Return since we have no target
|
||||||
|
if (!UpdateVictim())
|
||||||
|
return;
|
||||||
|
|
||||||
uint32 Frenzy_Timer;
|
//Frenzy_Timer
|
||||||
uint32 Wyvern_Timer;
|
if (!Frenzy && Frenzy_Timer <= diff)
|
||||||
uint32 Spit_Timer;
|
|
||||||
uint32 PoisonBolt_Timer;
|
|
||||||
uint32 NoxiousPoison_Timer;
|
|
||||||
uint32 FrenzyBack_Timer;
|
|
||||||
|
|
||||||
bool Frenzy;
|
|
||||||
bool Berserk;
|
|
||||||
|
|
||||||
void Reset() override
|
|
||||||
{
|
{
|
||||||
|
DoCast(me, SPELL_FRENZY);
|
||||||
|
Talk(EMOTE_FRENZY_KILL);
|
||||||
|
Frenzy = true;
|
||||||
|
PoisonBolt_Timer = 3000;
|
||||||
Frenzy_Timer = urand(25000, 35000);
|
Frenzy_Timer = urand(25000, 35000);
|
||||||
Wyvern_Timer = urand(18000, 28000);
|
|
||||||
Spit_Timer = 8000;
|
|
||||||
PoisonBolt_Timer = 4000;
|
|
||||||
NoxiousPoison_Timer = urand(10000, 20000);
|
|
||||||
FrenzyBack_Timer = 15000;
|
|
||||||
|
|
||||||
Frenzy = false;
|
|
||||||
Berserk = false;
|
|
||||||
}
|
}
|
||||||
|
else Frenzy_Timer -= diff;
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
// Wyvern Timer
|
||||||
|
if (Wyvern_Timer <= diff)
|
||||||
{
|
{
|
||||||
//Return since we have no target
|
DoCastAOE(SPELL_WYVERNSTING);
|
||||||
if (!UpdateVictim())
|
Wyvern_Timer = urand(15000, 32000);
|
||||||
return;
|
|
||||||
|
|
||||||
//Frenzy_Timer
|
|
||||||
if (!Frenzy && Frenzy_Timer <= diff)
|
|
||||||
{
|
|
||||||
DoCast(me, SPELL_FRENZY);
|
|
||||||
Talk(EMOTE_FRENZY_KILL);
|
|
||||||
Frenzy = true;
|
|
||||||
PoisonBolt_Timer = 3000;
|
|
||||||
Frenzy_Timer = urand(25000, 35000);
|
|
||||||
}
|
|
||||||
else Frenzy_Timer -= diff;
|
|
||||||
|
|
||||||
// Wyvern Timer
|
|
||||||
if (Wyvern_Timer <= diff)
|
|
||||||
{
|
|
||||||
DoCastAOE(SPELL_WYVERNSTING);
|
|
||||||
Wyvern_Timer = urand(15000, 32000);
|
|
||||||
}
|
|
||||||
else Wyvern_Timer -= diff;
|
|
||||||
|
|
||||||
//Spit Timer
|
|
||||||
if (Spit_Timer <= diff)
|
|
||||||
{
|
|
||||||
DoCastVictim(SPELL_ACIDSPIT);
|
|
||||||
Spit_Timer = urand(5000, 10000);
|
|
||||||
}
|
|
||||||
else Spit_Timer -= diff;
|
|
||||||
|
|
||||||
//NoxiousPoison_Timer
|
|
||||||
if (NoxiousPoison_Timer <= diff)
|
|
||||||
{
|
|
||||||
DoCastVictim(SPELL_NOXIOUSPOISON);
|
|
||||||
NoxiousPoison_Timer = urand(12000, 24000);
|
|
||||||
}
|
|
||||||
else NoxiousPoison_Timer -= diff;
|
|
||||||
|
|
||||||
//PoisonBolt only if frenzy or berserk
|
|
||||||
if (Frenzy || Berserk)
|
|
||||||
{
|
|
||||||
if (PoisonBolt_Timer <= diff)
|
|
||||||
{
|
|
||||||
DoCastVictim(SPELL_POISONBOLT);
|
|
||||||
PoisonBolt_Timer = 3000;
|
|
||||||
}
|
|
||||||
else PoisonBolt_Timer -= diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
//FrenzyBack_Timer
|
|
||||||
if (Frenzy && FrenzyBack_Timer <= diff)
|
|
||||||
{
|
|
||||||
me->InterruptNonMeleeSpells(false);
|
|
||||||
Frenzy = false;
|
|
||||||
FrenzyBack_Timer = 15000;
|
|
||||||
}
|
|
||||||
else FrenzyBack_Timer -= diff;
|
|
||||||
|
|
||||||
if (!Berserk && HealthBelowPct(31))
|
|
||||||
{
|
|
||||||
me->InterruptNonMeleeSpells(false);
|
|
||||||
Talk(EMOTE_BERSERK);
|
|
||||||
DoCast(me, SPELL_BERSERK);
|
|
||||||
Berserk = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
}
|
||||||
};
|
else Wyvern_Timer -= diff;
|
||||||
|
|
||||||
|
//Spit Timer
|
||||||
|
if (Spit_Timer <= diff)
|
||||||
|
{
|
||||||
|
DoCastVictim(SPELL_ACIDSPIT);
|
||||||
|
Spit_Timer = urand(5000, 10000);
|
||||||
|
}
|
||||||
|
else Spit_Timer -= diff;
|
||||||
|
|
||||||
|
//NoxiousPoison_Timer
|
||||||
|
if (NoxiousPoison_Timer <= diff)
|
||||||
|
{
|
||||||
|
DoCastVictim(SPELL_NOXIOUSPOISON);
|
||||||
|
NoxiousPoison_Timer = urand(12000, 24000);
|
||||||
|
}
|
||||||
|
else NoxiousPoison_Timer -= diff;
|
||||||
|
|
||||||
|
//PoisonBolt only if frenzy or berserk
|
||||||
|
if (Frenzy || Berserk)
|
||||||
|
{
|
||||||
|
if (PoisonBolt_Timer <= diff)
|
||||||
|
{
|
||||||
|
DoCastVictim(SPELL_POISONBOLT);
|
||||||
|
PoisonBolt_Timer = 3000;
|
||||||
|
}
|
||||||
|
else PoisonBolt_Timer -= diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
//FrenzyBack_Timer
|
||||||
|
if (Frenzy && FrenzyBack_Timer <= diff)
|
||||||
|
{
|
||||||
|
me->InterruptNonMeleeSpells(false);
|
||||||
|
Frenzy = false;
|
||||||
|
FrenzyBack_Timer = 15000;
|
||||||
|
}
|
||||||
|
else FrenzyBack_Timer -= diff;
|
||||||
|
|
||||||
|
if (!Berserk && HealthBelowPct(31))
|
||||||
|
{
|
||||||
|
me->InterruptNonMeleeSpells(false);
|
||||||
|
Talk(EMOTE_BERSERK);
|
||||||
|
DoCast(me, SPELL_BERSERK);
|
||||||
|
Berserk = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 26180 - Wyvern Sting
|
// 26180 - Wyvern Sting
|
||||||
@@ -173,6 +162,6 @@ class spell_huhuran_wyvern_sting : public AuraScript
|
|||||||
|
|
||||||
void AddSC_boss_huhuran()
|
void AddSC_boss_huhuran()
|
||||||
{
|
{
|
||||||
new boss_huhuran();
|
RegisterTempleOfAhnQirajCreatureAI(boss_huhuran);
|
||||||
RegisterSpellScript(spell_huhuran_wyvern_sting);
|
RegisterSpellScript(spell_huhuran_wyvern_sting);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,167 +36,145 @@ enum Spells
|
|||||||
SPELL_SUMMON_OURO = 26061
|
SPELL_SUMMON_OURO = 26061
|
||||||
};
|
};
|
||||||
|
|
||||||
class npc_ouro_spawner : public CreatureScript
|
struct npc_ouro_spawner : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
npc_ouro_spawner(Creature* creature) : ScriptedAI(creature)
|
||||||
npc_ouro_spawner() : CreatureScript("npc_ouro_spawner") {}
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const
|
|
||||||
{
|
{
|
||||||
return new npc_ouro_spawnerAI(creature);
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct npc_ouro_spawnerAI : public ScriptedAI
|
bool hasSummoned;
|
||||||
|
|
||||||
|
void Reset() override
|
||||||
{
|
{
|
||||||
npc_ouro_spawnerAI(Creature* creature) : ScriptedAI(creature)
|
hasSummoned = false;
|
||||||
|
DoCast(me, SPELL_DIRTMOUND_PASSIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveInLineOfSight(Unit* who) override
|
||||||
|
{
|
||||||
|
// Spawn Ouro on LoS check
|
||||||
|
if (!hasSummoned && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 40.0f))
|
||||||
{
|
{
|
||||||
Reset();
|
DoCast(me, SPELL_SUMMON_OURO);
|
||||||
|
hasSummoned = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasSummoned;
|
ScriptedAI::MoveInLineOfSight(who);
|
||||||
|
}
|
||||||
|
|
||||||
void Reset() override
|
void JustSummoned(Creature* creature) override
|
||||||
|
{
|
||||||
|
// Despawn when Ouro is spawned
|
||||||
|
if (creature->GetEntry() == NPC_OURO)
|
||||||
{
|
{
|
||||||
hasSummoned = false;
|
creature->SetInCombatWithZone();
|
||||||
DoCast(me, SPELL_DIRTMOUND_PASSIVE);
|
creature->CastSpell(creature, SPELL_BIRTH, false);
|
||||||
|
me->DespawnOrUnsummon();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* who) override
|
|
||||||
{
|
|
||||||
// Spawn Ouro on LoS check
|
|
||||||
if (!hasSummoned && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 40.0f))
|
|
||||||
{
|
|
||||||
DoCast(me, SPELL_SUMMON_OURO);
|
|
||||||
hasSummoned = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ScriptedAI::MoveInLineOfSight(who);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustSummoned(Creature* creature) override
|
|
||||||
{
|
|
||||||
// Despawn when Ouro is spawned
|
|
||||||
if (creature->GetEntry() == NPC_OURO)
|
|
||||||
{
|
|
||||||
creature->SetInCombatWithZone();
|
|
||||||
creature->CastSpell(creature, SPELL_BIRTH, false);
|
|
||||||
me->DespawnOrUnsummon();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_ouro : public CreatureScript
|
struct boss_ouro : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
boss_ouro(Creature* creature) : ScriptedAI(creature) { }
|
||||||
boss_ouro() : CreatureScript("boss_ouro") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
uint32 Sweep_Timer;
|
||||||
|
uint32 SandBlast_Timer;
|
||||||
|
uint32 Submerge_Timer;
|
||||||
|
uint32 Back_Timer;
|
||||||
|
uint32 ChangeTarget_Timer;
|
||||||
|
uint32 Spawn_Timer;
|
||||||
|
|
||||||
|
bool Enrage;
|
||||||
|
bool Submerged;
|
||||||
|
|
||||||
|
void Reset() override
|
||||||
{
|
{
|
||||||
return GetTempleOfAhnQirajAI<boss_ouroAI>(creature);
|
Sweep_Timer = urand(5000, 10000);
|
||||||
|
SandBlast_Timer = urand(20000, 35000);
|
||||||
|
Submerge_Timer = urand(90000, 150000);
|
||||||
|
Back_Timer = urand(30000, 45000);
|
||||||
|
ChangeTarget_Timer = urand(5000, 8000);
|
||||||
|
Spawn_Timer = urand(10000, 20000);
|
||||||
|
|
||||||
|
Enrage = false;
|
||||||
|
Submerged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct boss_ouroAI : public ScriptedAI
|
void EnterCombat(Unit* /*who*/) override
|
||||||
{
|
{
|
||||||
boss_ouroAI(Creature* creature) : ScriptedAI(creature) { }
|
DoCastVictim(SPELL_BIRTH);
|
||||||
|
}
|
||||||
|
|
||||||
uint32 Sweep_Timer;
|
void UpdateAI(uint32 diff) override
|
||||||
uint32 SandBlast_Timer;
|
{
|
||||||
uint32 Submerge_Timer;
|
//Return since we have no target
|
||||||
uint32 Back_Timer;
|
if (!UpdateVictim())
|
||||||
uint32 ChangeTarget_Timer;
|
return;
|
||||||
uint32 Spawn_Timer;
|
|
||||||
|
|
||||||
bool Enrage;
|
//Sweep_Timer
|
||||||
bool Submerged;
|
if (!Submerged && Sweep_Timer <= diff)
|
||||||
|
|
||||||
void Reset() override
|
|
||||||
{
|
{
|
||||||
Sweep_Timer = urand(5000, 10000);
|
DoCastVictim(SPELL_SWEEP);
|
||||||
|
Sweep_Timer = urand(15000, 30000);
|
||||||
|
}
|
||||||
|
else Sweep_Timer -= diff;
|
||||||
|
|
||||||
|
//SandBlast_Timer
|
||||||
|
if (!Submerged && SandBlast_Timer <= diff)
|
||||||
|
{
|
||||||
|
DoCastVictim(SPELL_SANDBLAST);
|
||||||
SandBlast_Timer = urand(20000, 35000);
|
SandBlast_Timer = urand(20000, 35000);
|
||||||
Submerge_Timer = urand(90000, 150000);
|
}
|
||||||
|
else SandBlast_Timer -= diff;
|
||||||
|
|
||||||
|
//Submerge_Timer
|
||||||
|
if (!Submerged && Submerge_Timer <= diff)
|
||||||
|
{
|
||||||
|
//Cast
|
||||||
|
me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE);
|
||||||
|
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||||
|
me->SetFaction(FACTION_FRIENDLY);
|
||||||
|
DoCast(me, SPELL_DIRTMOUND_PASSIVE);
|
||||||
|
|
||||||
|
Submerged = true;
|
||||||
Back_Timer = urand(30000, 45000);
|
Back_Timer = urand(30000, 45000);
|
||||||
ChangeTarget_Timer = urand(5000, 8000);
|
}
|
||||||
Spawn_Timer = urand(10000, 20000);
|
else Submerge_Timer -= diff;
|
||||||
|
|
||||||
|
//ChangeTarget_Timer
|
||||||
|
if (Submerged && ChangeTarget_Timer <= diff)
|
||||||
|
{
|
||||||
|
Unit* target = SelectTarget(SelectTargetMethod::Random, 0);
|
||||||
|
|
||||||
|
if (target)
|
||||||
|
me->NearTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), me->GetOrientation());
|
||||||
|
|
||||||
|
ChangeTarget_Timer = urand(10000, 20000);
|
||||||
|
}
|
||||||
|
else ChangeTarget_Timer -= diff;
|
||||||
|
|
||||||
|
//Back_Timer
|
||||||
|
if (Submerged && Back_Timer <= diff)
|
||||||
|
{
|
||||||
|
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||||
|
me->SetFaction(FACTION_MONSTER);
|
||||||
|
|
||||||
|
DoCastVictim(SPELL_GROUND_RUPTURE);
|
||||||
|
|
||||||
Enrage = false;
|
|
||||||
Submerged = false;
|
Submerged = false;
|
||||||
|
Submerge_Timer = urand(60000, 120000);
|
||||||
}
|
}
|
||||||
|
else Back_Timer -= diff;
|
||||||
|
|
||||||
void EnterCombat(Unit* /*who*/) override
|
DoMeleeAttackIfReady();
|
||||||
{
|
}
|
||||||
DoCastVictim(SPELL_BIRTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
|
||||||
//Return since we have no target
|
|
||||||
if (!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
//Sweep_Timer
|
|
||||||
if (!Submerged && Sweep_Timer <= diff)
|
|
||||||
{
|
|
||||||
DoCastVictim(SPELL_SWEEP);
|
|
||||||
Sweep_Timer = urand(15000, 30000);
|
|
||||||
}
|
|
||||||
else Sweep_Timer -= diff;
|
|
||||||
|
|
||||||
//SandBlast_Timer
|
|
||||||
if (!Submerged && SandBlast_Timer <= diff)
|
|
||||||
{
|
|
||||||
DoCastVictim(SPELL_SANDBLAST);
|
|
||||||
SandBlast_Timer = urand(20000, 35000);
|
|
||||||
}
|
|
||||||
else SandBlast_Timer -= diff;
|
|
||||||
|
|
||||||
//Submerge_Timer
|
|
||||||
if (!Submerged && Submerge_Timer <= diff)
|
|
||||||
{
|
|
||||||
//Cast
|
|
||||||
me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE);
|
|
||||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
|
||||||
me->SetFaction(FACTION_FRIENDLY);
|
|
||||||
DoCast(me, SPELL_DIRTMOUND_PASSIVE);
|
|
||||||
|
|
||||||
Submerged = true;
|
|
||||||
Back_Timer = urand(30000, 45000);
|
|
||||||
}
|
|
||||||
else Submerge_Timer -= diff;
|
|
||||||
|
|
||||||
//ChangeTarget_Timer
|
|
||||||
if (Submerged && ChangeTarget_Timer <= diff)
|
|
||||||
{
|
|
||||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0);
|
|
||||||
|
|
||||||
if (target)
|
|
||||||
me->NearTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), me->GetOrientation());
|
|
||||||
|
|
||||||
ChangeTarget_Timer = urand(10000, 20000);
|
|
||||||
}
|
|
||||||
else ChangeTarget_Timer -= diff;
|
|
||||||
|
|
||||||
//Back_Timer
|
|
||||||
if (Submerged && Back_Timer <= diff)
|
|
||||||
{
|
|
||||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
|
||||||
me->SetFaction(FACTION_MONSTER);
|
|
||||||
|
|
||||||
DoCastVictim(SPELL_GROUND_RUPTURE);
|
|
||||||
|
|
||||||
Submerged = false;
|
|
||||||
Submerge_Timer = urand(60000, 120000);
|
|
||||||
}
|
|
||||||
else Back_Timer -= diff;
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_ouro()
|
void AddSC_boss_ouro()
|
||||||
{
|
{
|
||||||
new npc_ouro_spawner();
|
RegisterTempleOfAhnQirajCreatureAI(npc_ouro_spawner);
|
||||||
new boss_ouro();
|
RegisterTempleOfAhnQirajCreatureAI(boss_ouro);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,183 +47,161 @@ enum Events
|
|||||||
|
|
||||||
uint32 const BlinkSpells[3] = { 4801, 8195, 20449 };
|
uint32 const BlinkSpells[3] = { 4801, 8195, 20449 };
|
||||||
|
|
||||||
class boss_skeram : public CreatureScript
|
struct boss_skeram : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_skeram(Creature* creature) : BossAI(creature, DATA_SKERAM) { }
|
||||||
boss_skeram() : CreatureScript("boss_skeram") { }
|
|
||||||
|
|
||||||
struct boss_skeramAI : public BossAI
|
void Reset() override
|
||||||
{
|
{
|
||||||
boss_skeramAI(Creature* creature) : BossAI(creature, DATA_SKERAM) { }
|
_Reset();
|
||||||
|
_flag = 0;
|
||||||
|
_hpct = 75.0f;
|
||||||
|
me->SetVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
void Reset() override
|
void KilledUnit(Unit* /*victim*/) override
|
||||||
|
{
|
||||||
|
Talk(SAY_SLAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnterEvadeMode(EvadeReason why) override
|
||||||
|
{
|
||||||
|
ScriptedAI::EnterEvadeMode(why);
|
||||||
|
if (me->IsSummon())
|
||||||
|
((TempSummon*)me)->UnSummon();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JustSummoned(Creature* creature) override
|
||||||
|
{
|
||||||
|
// Shift the boss and images (Get it? *Shift*?)
|
||||||
|
uint8 rand = 0;
|
||||||
|
if (_flag != 0)
|
||||||
{
|
{
|
||||||
_Reset();
|
|
||||||
_flag = 0;
|
|
||||||
_hpct = 75.0f;
|
|
||||||
me->SetVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KilledUnit(Unit* /*victim*/) override
|
|
||||||
{
|
|
||||||
Talk(SAY_SLAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnterEvadeMode(EvadeReason why) override
|
|
||||||
{
|
|
||||||
ScriptedAI::EnterEvadeMode(why);
|
|
||||||
if (me->IsSummon())
|
|
||||||
((TempSummon*)me)->UnSummon();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustSummoned(Creature* creature) override
|
|
||||||
{
|
|
||||||
// Shift the boss and images (Get it? *Shift*?)
|
|
||||||
uint8 rand = 0;
|
|
||||||
if (_flag != 0)
|
|
||||||
{
|
|
||||||
while (_flag & (1 << rand))
|
|
||||||
rand = urand(0, 2);
|
|
||||||
DoCast(me, BlinkSpells[rand]);
|
|
||||||
_flag |= (1 << rand);
|
|
||||||
_flag |= (1 << 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (_flag & (1 << rand))
|
while (_flag & (1 << rand))
|
||||||
rand = urand(0, 2);
|
rand = urand(0, 2);
|
||||||
creature->CastSpell(creature, BlinkSpells[rand]);
|
DoCast(me, BlinkSpells[rand]);
|
||||||
_flag |= (1 << rand);
|
_flag |= (1 << rand);
|
||||||
|
_flag |= (1 << 7);
|
||||||
if (_flag & (1 << 7))
|
|
||||||
_flag = 0;
|
|
||||||
|
|
||||||
float ImageHealthPct;
|
|
||||||
|
|
||||||
if (me->GetHealthPct() < 25.0f)
|
|
||||||
ImageHealthPct = 0.50f;
|
|
||||||
else if (me->GetHealthPct() < 50.0f)
|
|
||||||
ImageHealthPct = 0.20f;
|
|
||||||
else
|
|
||||||
ImageHealthPct = 0.10f;
|
|
||||||
|
|
||||||
creature->SetMaxHealth(me->GetMaxHealth() * ImageHealthPct);
|
|
||||||
creature->SetHealth(creature->GetMaxHealth() * (me->GetHealthPct() / 100.0f));
|
|
||||||
BossAI::JustSummoned(creature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
while (_flag & (1 << rand))
|
||||||
{
|
rand = urand(0, 2);
|
||||||
if (!me->IsSummon())
|
creature->CastSpell(creature, BlinkSpells[rand]);
|
||||||
{
|
_flag |= (1 << rand);
|
||||||
_JustDied();
|
|
||||||
Talk(SAY_DEATH);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
me->RemoveCorpse();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnterCombat(Unit* /*who*/) override
|
if (_flag & (1 << 7))
|
||||||
{
|
_flag = 0;
|
||||||
_EnterCombat();
|
|
||||||
events.Reset();
|
|
||||||
|
|
||||||
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, urand(6000, 12000));
|
float ImageHealthPct;
|
||||||
events.ScheduleEvent(EVENT_FULLFILMENT, 15000);
|
|
||||||
events.ScheduleEvent(EVENT_BLINK, urand(30000, 45000));
|
|
||||||
events.ScheduleEvent(EVENT_EARTH_SHOCK, 2000);
|
|
||||||
|
|
||||||
Talk(SAY_AGGRO);
|
if (me->GetHealthPct() < 25.0f)
|
||||||
}
|
ImageHealthPct = 0.50f;
|
||||||
|
else if (me->GetHealthPct() < 50.0f)
|
||||||
|
ImageHealthPct = 0.20f;
|
||||||
|
else
|
||||||
|
ImageHealthPct = 0.10f;
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
creature->SetMaxHealth(me->GetMaxHealth() * ImageHealthPct);
|
||||||
{
|
creature->SetHealth(creature->GetMaxHealth() * (me->GetHealthPct() / 100.0f));
|
||||||
if (!UpdateVictim())
|
BossAI::JustSummoned(creature);
|
||||||
return;
|
|
||||||
|
|
||||||
events.Update(diff);
|
|
||||||
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
switch (eventId)
|
|
||||||
{
|
|
||||||
case EVENT_ARCANE_EXPLOSION:
|
|
||||||
DoCastAOE(SPELL_ARCANE_EXPLOSION, true);
|
|
||||||
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, urand(8000, 18000));
|
|
||||||
break;
|
|
||||||
case EVENT_FULLFILMENT:
|
|
||||||
/// @todo For some weird reason boss does not cast this
|
|
||||||
// Spell actually works, tested in duel
|
|
||||||
DoCast(SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true), SPELL_TRUE_FULFILLMENT, true);
|
|
||||||
events.ScheduleEvent(EVENT_FULLFILMENT, urand(20000, 30000));
|
|
||||||
break;
|
|
||||||
case EVENT_BLINK:
|
|
||||||
DoCast(me, BlinkSpells[urand(0, 2)]);
|
|
||||||
DoResetThreat();
|
|
||||||
me->SetVisible(true);
|
|
||||||
events.ScheduleEvent(EVENT_BLINK, urand(10000, 30000));
|
|
||||||
break;
|
|
||||||
case EVENT_EARTH_SHOCK:
|
|
||||||
DoCastVictim(SPELL_EARTH_SHOCK);
|
|
||||||
events.ScheduleEvent(EVENT_EARTH_SHOCK, 2000);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!me->IsSummon() && me->GetHealthPct() < _hpct)
|
|
||||||
{
|
|
||||||
DoCast(me, SPELL_SUMMON_IMAGES, true);
|
|
||||||
Talk(SAY_SPLIT);
|
|
||||||
_hpct -= 25.0f;
|
|
||||||
me->SetVisible(false);
|
|
||||||
events.RescheduleEvent(EVENT_BLINK, 2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (me->IsWithinMeleeRange(me->GetVictim()))
|
|
||||||
{
|
|
||||||
events.RescheduleEvent(EVENT_EARTH_SHOCK, 2000);
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
float _hpct;
|
|
||||||
uint8 _flag;
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
|
||||||
return GetTempleOfAhnQirajAI<boss_skeramAI>(creature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JustDied(Unit* /*killer*/) override
|
||||||
|
{
|
||||||
|
if (!me->IsSummon())
|
||||||
|
{
|
||||||
|
_JustDied();
|
||||||
|
Talk(SAY_DEATH);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
me->RemoveCorpse();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnterCombat(Unit* /*who*/) override
|
||||||
|
{
|
||||||
|
_EnterCombat();
|
||||||
|
events.Reset();
|
||||||
|
|
||||||
|
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 6s, 12s);
|
||||||
|
events.ScheduleEvent(EVENT_FULLFILMENT, 15s);
|
||||||
|
events.ScheduleEvent(EVENT_BLINK, 30s, 45s);
|
||||||
|
events.ScheduleEvent(EVENT_EARTH_SHOCK, 2s);
|
||||||
|
|
||||||
|
Talk(SAY_AGGRO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
if (!UpdateVictim())
|
||||||
|
return;
|
||||||
|
|
||||||
|
events.Update(diff);
|
||||||
|
|
||||||
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
|
{
|
||||||
|
switch (eventId)
|
||||||
|
{
|
||||||
|
case EVENT_ARCANE_EXPLOSION:
|
||||||
|
DoCastAOE(SPELL_ARCANE_EXPLOSION, true);
|
||||||
|
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 8s, 18s);
|
||||||
|
break;
|
||||||
|
case EVENT_FULLFILMENT:
|
||||||
|
/// @todo For some weird reason boss does not cast this
|
||||||
|
// Spell actually works, tested in duel
|
||||||
|
DoCast(SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true), SPELL_TRUE_FULFILLMENT, true);
|
||||||
|
events.ScheduleEvent(EVENT_FULLFILMENT, 20s, 30s);
|
||||||
|
break;
|
||||||
|
case EVENT_BLINK:
|
||||||
|
DoCast(me, BlinkSpells[urand(0, 2)]);
|
||||||
|
DoResetThreat();
|
||||||
|
me->SetVisible(true);
|
||||||
|
events.ScheduleEvent(EVENT_BLINK, 10s, 30s);
|
||||||
|
break;
|
||||||
|
case EVENT_EARTH_SHOCK:
|
||||||
|
DoCastVictim(SPELL_EARTH_SHOCK);
|
||||||
|
events.ScheduleEvent(EVENT_EARTH_SHOCK, 2s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!me->IsSummon() && me->GetHealthPct() < _hpct)
|
||||||
|
{
|
||||||
|
DoCast(me, SPELL_SUMMON_IMAGES, true);
|
||||||
|
Talk(SAY_SPLIT);
|
||||||
|
_hpct -= 25.0f;
|
||||||
|
me->SetVisible(false);
|
||||||
|
events.RescheduleEvent(EVENT_BLINK, 2s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (me->IsWithinMeleeRange(me->GetVictim()))
|
||||||
|
{
|
||||||
|
events.RescheduleEvent(EVENT_EARTH_SHOCK, 2s);
|
||||||
|
DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
float _hpct;
|
||||||
|
uint8 _flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
class spell_skeram_arcane_explosion : public SpellScriptLoader
|
class spell_skeram_arcane_explosion : public SpellScript
|
||||||
{
|
{
|
||||||
public:
|
PrepareSpellScript(spell_skeram_arcane_explosion);
|
||||||
spell_skeram_arcane_explosion() : SpellScriptLoader("spell_skeram_arcane_explosion") { }
|
|
||||||
|
|
||||||
class spell_skeram_arcane_explosion_SpellScript : public SpellScript
|
void FilterTargets(std::list<WorldObject*>& targets)
|
||||||
{
|
{
|
||||||
PrepareSpellScript(spell_skeram_arcane_explosion_SpellScript);
|
targets.remove_if(PlayerOrPetCheck());
|
||||||
|
}
|
||||||
|
|
||||||
void FilterTargets(std::list<WorldObject*>& targets)
|
void Register() override
|
||||||
{
|
|
||||||
targets.remove_if(PlayerOrPetCheck());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Register() override
|
|
||||||
{
|
|
||||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_skeram_arcane_explosion_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
SpellScript* GetSpellScript() const override
|
|
||||||
{
|
{
|
||||||
return new spell_skeram_arcane_explosion_SpellScript();
|
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_skeram_arcane_explosion::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_skeram()
|
void AddSC_boss_skeram()
|
||||||
{
|
{
|
||||||
new boss_skeram();
|
RegisterTempleOfAhnQirajCreatureAI(boss_skeram);
|
||||||
new spell_skeram_arcane_explosion();
|
RegisterSpellScript(spell_skeram_arcane_explosion);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -377,223 +377,203 @@ struct boss_twinemperorsAI : public ScriptedAI
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_veknilash : public CreatureScript
|
struct boss_veknilash : public boss_twinemperorsAI
|
||||||
{
|
{
|
||||||
public:
|
boss_veknilash(Creature* creature) : boss_twinemperorsAI(creature) { }
|
||||||
boss_veknilash() : CreatureScript("boss_veknilash") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
bool IAmVeklor() override { return false; }
|
||||||
|
|
||||||
|
uint32 UpperCut_Timer;
|
||||||
|
uint32 UnbalancingStrike_Timer;
|
||||||
|
uint32 Scarabs_Timer;
|
||||||
|
int Rand;
|
||||||
|
int RandX;
|
||||||
|
int RandY;
|
||||||
|
|
||||||
|
Creature* Summoned;
|
||||||
|
|
||||||
|
void Reset() override
|
||||||
{
|
{
|
||||||
return GetTempleOfAhnQirajAI<boss_veknilashAI>(creature);
|
TwinReset();
|
||||||
|
UpperCut_Timer = urand(14000, 29000);
|
||||||
|
UnbalancingStrike_Timer = urand(8000, 18000);
|
||||||
|
Scarabs_Timer = urand(7000, 14000);
|
||||||
|
|
||||||
|
//Added. Can be removed if its included in DB.
|
||||||
|
me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct boss_veknilashAI : public boss_twinemperorsAI
|
void CastSpellOnBug(Creature* target) override
|
||||||
{
|
{
|
||||||
bool IAmVeklor() override {return false;}
|
target->SetFaction(FACTION_MONSTER);
|
||||||
boss_veknilashAI(Creature* creature) : boss_twinemperorsAI(creature) { }
|
target->AI()->AttackStart(me->GetThreatMgr().getHostileTarget());
|
||||||
|
target->AddAura(SPELL_MUTATE_BUG, target);
|
||||||
|
target->SetFullHealth();
|
||||||
|
}
|
||||||
|
|
||||||
uint32 UpperCut_Timer;
|
void UpdateAI(uint32 diff) override
|
||||||
uint32 UnbalancingStrike_Timer;
|
{
|
||||||
uint32 Scarabs_Timer;
|
//Return since we have no target
|
||||||
int Rand;
|
if (!UpdateVictim())
|
||||||
int RandX;
|
return;
|
||||||
int RandY;
|
|
||||||
|
|
||||||
Creature* Summoned;
|
if (!TryActivateAfterTTelep(diff))
|
||||||
|
return;
|
||||||
|
|
||||||
void Reset() override
|
//UnbalancingStrike_Timer
|
||||||
|
if (UnbalancingStrike_Timer <= diff)
|
||||||
{
|
{
|
||||||
TwinReset();
|
DoCastVictim(SPELL_UNBALANCING_STRIKE);
|
||||||
UpperCut_Timer = urand(14000, 29000);
|
UnbalancingStrike_Timer = 8000 + rand() % 12000;
|
||||||
UnbalancingStrike_Timer = urand(8000, 18000);
|
|
||||||
Scarabs_Timer = urand(7000, 14000);
|
|
||||||
|
|
||||||
//Added. Can be removed if its included in DB.
|
|
||||||
me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true);
|
|
||||||
}
|
}
|
||||||
|
else UnbalancingStrike_Timer -= diff;
|
||||||
|
|
||||||
void CastSpellOnBug(Creature* target) override
|
if (UpperCut_Timer <= diff)
|
||||||
{
|
{
|
||||||
target->SetFaction(FACTION_MONSTER);
|
Unit* randomMelee = SelectTarget(SelectTargetMethod::Random, 0, NOMINAL_MELEE_RANGE, true);
|
||||||
target->AI()->AttackStart(me->GetThreatMgr().getHostileTarget());
|
if (randomMelee)
|
||||||
target->AddAura(SPELL_MUTATE_BUG, target);
|
DoCast(randomMelee, SPELL_UPPERCUT);
|
||||||
target->SetFullHealth();
|
UpperCut_Timer = 15000 + rand() % 15000;
|
||||||
}
|
}
|
||||||
|
else UpperCut_Timer -= diff;
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
HandleBugs(diff);
|
||||||
|
|
||||||
|
//Heal brother when 60yrds close
|
||||||
|
TryHealBrother(diff);
|
||||||
|
|
||||||
|
//Teleporting to brother
|
||||||
|
if (Teleport_Timer <= diff)
|
||||||
{
|
{
|
||||||
//Return since we have no target
|
TeleportToMyBrother();
|
||||||
if (!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!TryActivateAfterTTelep(diff))
|
|
||||||
return;
|
|
||||||
|
|
||||||
//UnbalancingStrike_Timer
|
|
||||||
if (UnbalancingStrike_Timer <= diff)
|
|
||||||
{
|
|
||||||
DoCastVictim(SPELL_UNBALANCING_STRIKE);
|
|
||||||
UnbalancingStrike_Timer = 8000 + rand() % 12000;
|
|
||||||
}
|
|
||||||
else UnbalancingStrike_Timer -= diff;
|
|
||||||
|
|
||||||
if (UpperCut_Timer <= diff)
|
|
||||||
{
|
|
||||||
Unit* randomMelee = SelectTarget(SelectTargetMethod::Random, 0, NOMINAL_MELEE_RANGE, true);
|
|
||||||
if (randomMelee)
|
|
||||||
DoCast(randomMelee, SPELL_UPPERCUT);
|
|
||||||
UpperCut_Timer = 15000 + rand() % 15000;
|
|
||||||
}
|
|
||||||
else UpperCut_Timer -= diff;
|
|
||||||
|
|
||||||
HandleBugs(diff);
|
|
||||||
|
|
||||||
//Heal brother when 60yrds close
|
|
||||||
TryHealBrother(diff);
|
|
||||||
|
|
||||||
//Teleporting to brother
|
|
||||||
if (Teleport_Timer <= diff)
|
|
||||||
{
|
|
||||||
TeleportToMyBrother();
|
|
||||||
}
|
|
||||||
else Teleport_Timer -= diff;
|
|
||||||
|
|
||||||
CheckEnrage(diff);
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
}
|
||||||
};
|
else Teleport_Timer -= diff;
|
||||||
|
|
||||||
|
CheckEnrage(diff);
|
||||||
|
|
||||||
|
DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_veklor : public CreatureScript
|
struct boss_veklor : public boss_twinemperorsAI
|
||||||
{
|
{
|
||||||
public:
|
boss_veklor(Creature* creature) : boss_twinemperorsAI(creature) { }
|
||||||
boss_veklor() : CreatureScript("boss_veklor") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
bool IAmVeklor() override { return true; }
|
||||||
|
|
||||||
|
uint32 ShadowBolt_Timer;
|
||||||
|
uint32 Blizzard_Timer;
|
||||||
|
uint32 ArcaneBurst_Timer;
|
||||||
|
uint32 Scorpions_Timer;
|
||||||
|
int Rand;
|
||||||
|
int RandX;
|
||||||
|
|
||||||
|
Creature* Summoned;
|
||||||
|
|
||||||
|
void Reset() override
|
||||||
{
|
{
|
||||||
return GetTempleOfAhnQirajAI<boss_veklorAI>(creature);
|
TwinReset();
|
||||||
|
ShadowBolt_Timer = 0;
|
||||||
|
Blizzard_Timer = urand(15000, 20000);
|
||||||
|
ArcaneBurst_Timer = 1000;
|
||||||
|
Scorpions_Timer = urand(7000, 14000);
|
||||||
|
|
||||||
|
//Added. Can be removed if its included in DB.
|
||||||
|
me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct boss_veklorAI : public boss_twinemperorsAI
|
void CastSpellOnBug(Creature* target) override
|
||||||
{
|
{
|
||||||
bool IAmVeklor() override {return true;}
|
target->SetFaction(FACTION_MONSTER);
|
||||||
boss_veklorAI(Creature* creature) : boss_twinemperorsAI(creature) { }
|
target->AddAura(SPELL_EXPLODEBUG, target);
|
||||||
|
target->SetFullHealth();
|
||||||
|
}
|
||||||
|
|
||||||
uint32 ShadowBolt_Timer;
|
void UpdateAI(uint32 diff) override
|
||||||
uint32 Blizzard_Timer;
|
{
|
||||||
uint32 ArcaneBurst_Timer;
|
//Return since we have no target
|
||||||
uint32 Scorpions_Timer;
|
if (!UpdateVictim())
|
||||||
int Rand;
|
return;
|
||||||
int RandX;
|
|
||||||
|
|
||||||
Creature* Summoned;
|
// reset arcane burst after teleport - we need to do this because
|
||||||
|
// when VL jumps to VN's location there will be a warrior who will get only 2s to run away
|
||||||
|
// which is almost impossible
|
||||||
|
if (AfterTeleport)
|
||||||
|
ArcaneBurst_Timer = 5000;
|
||||||
|
if (!TryActivateAfterTTelep(diff))
|
||||||
|
return;
|
||||||
|
|
||||||
void Reset() override
|
//ShadowBolt_Timer
|
||||||
|
if (ShadowBolt_Timer <= diff)
|
||||||
{
|
{
|
||||||
TwinReset();
|
if (!me->IsWithinDist(me->GetVictim(), 45.0f))
|
||||||
ShadowBolt_Timer = 0;
|
me->GetMotionMaster()->MoveChase(me->GetVictim(), VEKLOR_DIST, 0);
|
||||||
Blizzard_Timer = urand(15000, 20000);
|
else
|
||||||
ArcaneBurst_Timer = 1000;
|
DoCastVictim(SPELL_SHADOWBOLT);
|
||||||
Scorpions_Timer = urand(7000, 14000);
|
ShadowBolt_Timer = 2000;
|
||||||
|
|
||||||
//Added. Can be removed if its included in DB.
|
|
||||||
me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true);
|
|
||||||
}
|
}
|
||||||
|
else ShadowBolt_Timer -= diff;
|
||||||
|
|
||||||
void CastSpellOnBug(Creature* target) override
|
//Blizzard_Timer
|
||||||
|
if (Blizzard_Timer <= diff)
|
||||||
{
|
{
|
||||||
target->SetFaction(FACTION_MONSTER);
|
Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 45, true);
|
||||||
target->AddAura(SPELL_EXPLODEBUG, target);
|
if (target)
|
||||||
target->SetFullHealth();
|
{
|
||||||
|
DoCast(target, SPELL_BLIZZARD);
|
||||||
|
}
|
||||||
|
Blizzard_Timer = 15000 + rand() % 15000;
|
||||||
}
|
}
|
||||||
|
else Blizzard_Timer -= diff;
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
if (ArcaneBurst_Timer <= diff)
|
||||||
{
|
{
|
||||||
//Return since we have no target
|
Unit* mvic;
|
||||||
if (!UpdateVictim())
|
if ((mvic = SelectTarget(SelectTargetMethod::MaxDistance, 0, NOMINAL_MELEE_RANGE, true)) != nullptr)
|
||||||
return;
|
{
|
||||||
|
DoCast(mvic, SPELL_ARCANEBURST);
|
||||||
// reset arcane burst after teleport - we need to do this because
|
|
||||||
// when VL jumps to VN's location there will be a warrior who will get only 2s to run away
|
|
||||||
// which is almost impossible
|
|
||||||
if (AfterTeleport)
|
|
||||||
ArcaneBurst_Timer = 5000;
|
ArcaneBurst_Timer = 5000;
|
||||||
if (!TryActivateAfterTTelep(diff))
|
|
||||||
return;
|
|
||||||
|
|
||||||
//ShadowBolt_Timer
|
|
||||||
if (ShadowBolt_Timer <= diff)
|
|
||||||
{
|
|
||||||
if (!me->IsWithinDist(me->GetVictim(), 45.0f))
|
|
||||||
me->GetMotionMaster()->MoveChase(me->GetVictim(), VEKLOR_DIST, 0);
|
|
||||||
else
|
|
||||||
DoCastVictim(SPELL_SHADOWBOLT);
|
|
||||||
ShadowBolt_Timer = 2000;
|
|
||||||
}
|
}
|
||||||
else ShadowBolt_Timer -= diff;
|
|
||||||
|
|
||||||
//Blizzard_Timer
|
|
||||||
if (Blizzard_Timer <= diff)
|
|
||||||
{
|
|
||||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 45, true);
|
|
||||||
if (target)
|
|
||||||
{
|
|
||||||
DoCast(target, SPELL_BLIZZARD);
|
|
||||||
}
|
|
||||||
Blizzard_Timer = 15000 + rand() % 15000;
|
|
||||||
}
|
|
||||||
else Blizzard_Timer -= diff;
|
|
||||||
|
|
||||||
if (ArcaneBurst_Timer <= diff)
|
|
||||||
{
|
|
||||||
Unit* mvic;
|
|
||||||
if ((mvic = SelectTarget(SelectTargetMethod::MaxDistance, 0, NOMINAL_MELEE_RANGE, true)) != nullptr)
|
|
||||||
{
|
|
||||||
DoCast(mvic, SPELL_ARCANEBURST);
|
|
||||||
ArcaneBurst_Timer = 5000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else ArcaneBurst_Timer -= diff;
|
|
||||||
|
|
||||||
HandleBugs(diff);
|
|
||||||
|
|
||||||
//Heal brother when 60yrds close
|
|
||||||
TryHealBrother(diff);
|
|
||||||
|
|
||||||
//Teleporting to brother
|
|
||||||
if (Teleport_Timer <= diff)
|
|
||||||
{
|
|
||||||
TeleportToMyBrother();
|
|
||||||
}
|
|
||||||
else Teleport_Timer -= diff;
|
|
||||||
|
|
||||||
CheckEnrage(diff);
|
|
||||||
|
|
||||||
//VL doesn't melee
|
|
||||||
//DoMeleeAttackIfReady();
|
|
||||||
}
|
}
|
||||||
|
else ArcaneBurst_Timer -= diff;
|
||||||
|
|
||||||
void AttackStart(Unit* who) override
|
HandleBugs(diff);
|
||||||
|
|
||||||
|
//Heal brother when 60yrds close
|
||||||
|
TryHealBrother(diff);
|
||||||
|
|
||||||
|
//Teleporting to brother
|
||||||
|
if (Teleport_Timer <= diff)
|
||||||
{
|
{
|
||||||
if (!who)
|
TeleportToMyBrother();
|
||||||
return;
|
}
|
||||||
|
else Teleport_Timer -= diff;
|
||||||
|
|
||||||
if (who->isTargetableForAttack())
|
CheckEnrage(diff);
|
||||||
|
|
||||||
|
//VL doesn't melee
|
||||||
|
//DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttackStart(Unit* who) override
|
||||||
|
{
|
||||||
|
if (!who)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (who->isTargetableForAttack())
|
||||||
|
{
|
||||||
|
// VL doesn't melee
|
||||||
|
if (me->Attack(who, false))
|
||||||
{
|
{
|
||||||
// VL doesn't melee
|
me->GetMotionMaster()->MoveChase(who, VEKLOR_DIST, 0);
|
||||||
if (me->Attack(who, false))
|
me->AddThreat(who, 0.0f);
|
||||||
{
|
|
||||||
me->GetMotionMaster()->MoveChase(who, VEKLOR_DIST, 0);
|
|
||||||
me->AddThreat(who, 0.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_twinemperors()
|
void AddSC_boss_twinemperors()
|
||||||
{
|
{
|
||||||
new boss_veknilash();
|
RegisterTempleOfAhnQirajCreatureAI(boss_veknilash);
|
||||||
new boss_veklor();
|
RegisterTempleOfAhnQirajCreatureAI(boss_veklor);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,223 +84,201 @@ enum MovePoints
|
|||||||
Position const ViscidusCoord = { -7992.36f, 908.19f, -52.62f, 1.68f }; /// @todo Visci isn't in room middle
|
Position const ViscidusCoord = { -7992.36f, 908.19f, -52.62f, 1.68f }; /// @todo Visci isn't in room middle
|
||||||
float const RoomRadius = 40.0f; /// @todo Not sure if its correct
|
float const RoomRadius = 40.0f; /// @todo Not sure if its correct
|
||||||
|
|
||||||
class boss_viscidus : public CreatureScript
|
struct boss_viscidus : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_viscidus(Creature* creature) : BossAI(creature, DATA_VISCIDUS) { }
|
||||||
boss_viscidus() : CreatureScript("boss_viscidus") { }
|
|
||||||
|
|
||||||
struct boss_viscidusAI : public BossAI
|
void Reset() override
|
||||||
{
|
{
|
||||||
boss_viscidusAI(Creature* creature) : BossAI(creature, DATA_VISCIDUS) { }
|
_Reset();
|
||||||
|
_hitcounter = 0;
|
||||||
|
_phase = PHASE_FROST;
|
||||||
|
}
|
||||||
|
|
||||||
void Reset() override
|
void DamageTaken(Unit* attacker, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
|
||||||
|
{
|
||||||
|
if (!attacker || _phase != PHASE_MELEE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
++_hitcounter;
|
||||||
|
|
||||||
|
if (attacker->HasUnitState(UNIT_STATE_MELEE_ATTACKING) && _hitcounter >= HITCOUNTER_EXPLODE)
|
||||||
{
|
{
|
||||||
_Reset();
|
Talk(EMOTE_EXPLODE);
|
||||||
_hitcounter = 0;
|
events.Reset();
|
||||||
_phase = PHASE_FROST;
|
_phase = PHASE_GLOB;
|
||||||
|
DoCast(me, SPELL_VISCIDUS_EXPLODE);
|
||||||
|
me->SetVisible(false);
|
||||||
|
me->RemoveAura(SPELL_TOXIN);
|
||||||
|
me->RemoveAura(SPELL_VISCIDUS_FREEZE);
|
||||||
|
|
||||||
|
uint8 NumGlobes = me->GetHealthPct() / 5.0f;
|
||||||
|
for (uint8 i = 0; i < NumGlobes; ++i)
|
||||||
|
{
|
||||||
|
float Angle = i * 2 * M_PI / NumGlobes;
|
||||||
|
float X = ViscidusCoord.GetPositionX() + std::cos(Angle) * RoomRadius;
|
||||||
|
float Y = ViscidusCoord.GetPositionY() + std::sin(Angle) * RoomRadius;
|
||||||
|
float Z = -35.0f;
|
||||||
|
|
||||||
|
if (TempSummon* Glob = me->SummonCreature(NPC_GLOB_OF_VISCIDUS, X, Y, Z))
|
||||||
|
{
|
||||||
|
Glob->UpdateAllowedPositionZ(X, Y, Z);
|
||||||
|
Glob->NearTeleportTo(X, Y, Z, 0.0f);
|
||||||
|
Glob->GetMotionMaster()->MovePoint(ROOM_CENTER, ViscidusCoord);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else if (_hitcounter == HITCOUNTER_SHATTER)
|
||||||
|
Talk(EMOTE_SHATTER);
|
||||||
|
else if (_hitcounter == HITCOUNTER_CRACK)
|
||||||
|
Talk(EMOTE_CRACK);
|
||||||
|
}
|
||||||
|
|
||||||
void DamageTaken(Unit* attacker, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
|
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
||||||
|
{
|
||||||
|
if ((spell->GetSchoolMask() & SPELL_SCHOOL_MASK_FROST) && _phase == PHASE_FROST && me->GetHealthPct() > 5.0f)
|
||||||
{
|
{
|
||||||
if (!attacker || _phase != PHASE_MELEE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
++_hitcounter;
|
++_hitcounter;
|
||||||
|
|
||||||
if (attacker->HasUnitState(UNIT_STATE_MELEE_ATTACKING) && _hitcounter >= HITCOUNTER_EXPLODE)
|
if (_hitcounter >= HITCOUNTER_FREEZE)
|
||||||
{
|
{
|
||||||
Talk(EMOTE_EXPLODE);
|
|
||||||
events.Reset();
|
|
||||||
_phase = PHASE_GLOB;
|
|
||||||
DoCast(me, SPELL_VISCIDUS_EXPLODE);
|
|
||||||
me->SetVisible(false);
|
|
||||||
me->RemoveAura(SPELL_TOXIN);
|
|
||||||
me->RemoveAura(SPELL_VISCIDUS_FREEZE);
|
|
||||||
|
|
||||||
uint8 NumGlobes = me->GetHealthPct() / 5.0f;
|
|
||||||
for (uint8 i = 0; i < NumGlobes; ++i)
|
|
||||||
{
|
|
||||||
float Angle = i * 2 * M_PI / NumGlobes;
|
|
||||||
float X = ViscidusCoord.GetPositionX() + std::cos(Angle) * RoomRadius;
|
|
||||||
float Y = ViscidusCoord.GetPositionY() + std::sin(Angle) * RoomRadius;
|
|
||||||
float Z = -35.0f;
|
|
||||||
|
|
||||||
if (TempSummon* Glob = me->SummonCreature(NPC_GLOB_OF_VISCIDUS, X, Y, Z))
|
|
||||||
{
|
|
||||||
Glob->UpdateAllowedPositionZ(X, Y, Z);
|
|
||||||
Glob->NearTeleportTo(X, Y, Z, 0.0f);
|
|
||||||
Glob->GetMotionMaster()->MovePoint(ROOM_CENTER, ViscidusCoord);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (_hitcounter == HITCOUNTER_SHATTER)
|
|
||||||
Talk(EMOTE_SHATTER);
|
|
||||||
else if (_hitcounter == HITCOUNTER_CRACK)
|
|
||||||
Talk(EMOTE_CRACK);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
|
||||||
{
|
|
||||||
if ((spell->GetSchoolMask() & SPELL_SCHOOL_MASK_FROST) && _phase == PHASE_FROST && me->GetHealthPct() > 5.0f)
|
|
||||||
{
|
|
||||||
++_hitcounter;
|
|
||||||
|
|
||||||
if (_hitcounter >= HITCOUNTER_FREEZE)
|
|
||||||
{
|
|
||||||
_hitcounter = 0;
|
|
||||||
Talk(EMOTE_FROZEN);
|
|
||||||
_phase = PHASE_MELEE;
|
|
||||||
DoCast(me, SPELL_VISCIDUS_FREEZE);
|
|
||||||
me->RemoveAura(SPELL_VISCIDUS_SLOWED_MORE);
|
|
||||||
events.ScheduleEvent(EVENT_RESET_PHASE, 15000);
|
|
||||||
}
|
|
||||||
else if (_hitcounter >= HITCOUNTER_SLOW_MORE)
|
|
||||||
{
|
|
||||||
Talk(EMOTE_FREEZE);
|
|
||||||
me->RemoveAura(SPELL_VISCIDUS_SLOWED);
|
|
||||||
DoCast(me, SPELL_VISCIDUS_SLOWED_MORE);
|
|
||||||
}
|
|
||||||
else if (_hitcounter >= HITCOUNTER_SLOW)
|
|
||||||
{
|
|
||||||
Talk(EMOTE_SLOW);
|
|
||||||
DoCast(me, SPELL_VISCIDUS_SLOWED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnterCombat(Unit* /*who*/) override
|
|
||||||
{
|
|
||||||
_EnterCombat();
|
|
||||||
events.Reset();
|
|
||||||
InitSpells();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitSpells()
|
|
||||||
{
|
|
||||||
DoCast(me, SPELL_TOXIN);
|
|
||||||
events.ScheduleEvent(EVENT_POISONBOLT_VOLLEY, urand(10000, 15000));
|
|
||||||
events.ScheduleEvent(EVENT_POISON_SHOCK, urand(7000, 12000));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnterEvadeMode(EvadeReason why) override
|
|
||||||
{
|
|
||||||
summons.DespawnAll();
|
|
||||||
ScriptedAI::EnterEvadeMode(why);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
|
||||||
{
|
|
||||||
DoCast(me, SPELL_VISCIDUS_SUICIDE);
|
|
||||||
summons.DespawnAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
|
||||||
if (!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_phase == PHASE_GLOB && summons.empty())
|
|
||||||
{
|
|
||||||
DoResetThreat();
|
|
||||||
me->NearTeleportTo(ViscidusCoord.GetPositionX(),
|
|
||||||
ViscidusCoord.GetPositionY(),
|
|
||||||
ViscidusCoord.GetPositionZ(),
|
|
||||||
ViscidusCoord.GetOrientation());
|
|
||||||
|
|
||||||
_hitcounter = 0;
|
_hitcounter = 0;
|
||||||
_phase = PHASE_FROST;
|
Talk(EMOTE_FROZEN);
|
||||||
InitSpells();
|
_phase = PHASE_MELEE;
|
||||||
me->SetVisible(true);
|
DoCast(me, SPELL_VISCIDUS_FREEZE);
|
||||||
|
me->RemoveAura(SPELL_VISCIDUS_SLOWED_MORE);
|
||||||
|
events.ScheduleEvent(EVENT_RESET_PHASE, 15000);
|
||||||
}
|
}
|
||||||
|
else if (_hitcounter >= HITCOUNTER_SLOW_MORE)
|
||||||
events.Update(diff);
|
|
||||||
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
|
||||||
{
|
{
|
||||||
switch (eventId)
|
Talk(EMOTE_FREEZE);
|
||||||
{
|
me->RemoveAura(SPELL_VISCIDUS_SLOWED);
|
||||||
case EVENT_POISONBOLT_VOLLEY:
|
DoCast(me, SPELL_VISCIDUS_SLOWED_MORE);
|
||||||
DoCast(me, SPELL_POISONBOLT_VOLLEY);
|
|
||||||
events.ScheduleEvent(EVENT_POISONBOLT_VOLLEY, urand(10000, 15000));
|
|
||||||
break;
|
|
||||||
case EVENT_POISON_SHOCK:
|
|
||||||
DoCast(me, SPELL_POISON_SHOCK);
|
|
||||||
events.ScheduleEvent(EVENT_POISON_SHOCK, urand(7000, 12000));
|
|
||||||
break;
|
|
||||||
case EVENT_RESET_PHASE:
|
|
||||||
_hitcounter = 0;
|
|
||||||
_phase = PHASE_FROST;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if (_hitcounter >= HITCOUNTER_SLOW)
|
||||||
|
{
|
||||||
|
Talk(EMOTE_SLOW);
|
||||||
|
DoCast(me, SPELL_VISCIDUS_SLOWED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_phase != PHASE_GLOB)
|
void EnterCombat(Unit* /*who*/) override
|
||||||
DoMeleeAttackIfReady();
|
{
|
||||||
|
_EnterCombat();
|
||||||
|
events.Reset();
|
||||||
|
InitSpells();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitSpells()
|
||||||
|
{
|
||||||
|
DoCast(me, SPELL_TOXIN);
|
||||||
|
events.ScheduleEvent(EVENT_POISONBOLT_VOLLEY, 10s, 15s);
|
||||||
|
events.ScheduleEvent(EVENT_POISON_SHOCK, 7s, 12s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnterEvadeMode(EvadeReason why) override
|
||||||
|
{
|
||||||
|
summons.DespawnAll();
|
||||||
|
ScriptedAI::EnterEvadeMode(why);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JustDied(Unit* /*killer*/) override
|
||||||
|
{
|
||||||
|
DoCast(me, SPELL_VISCIDUS_SUICIDE);
|
||||||
|
summons.DespawnAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
if (!UpdateVictim())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_phase == PHASE_GLOB && summons.empty())
|
||||||
|
{
|
||||||
|
DoResetThreat();
|
||||||
|
me->NearTeleportTo(ViscidusCoord.GetPositionX(),
|
||||||
|
ViscidusCoord.GetPositionY(),
|
||||||
|
ViscidusCoord.GetPositionZ(),
|
||||||
|
ViscidusCoord.GetOrientation());
|
||||||
|
|
||||||
|
_hitcounter = 0;
|
||||||
|
_phase = PHASE_FROST;
|
||||||
|
InitSpells();
|
||||||
|
me->SetVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
events.Update(diff);
|
||||||
uint8 _hitcounter;
|
|
||||||
Phases _phase;
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
return GetTempleOfAhnQirajAI<boss_viscidusAI>(creature);
|
switch (eventId)
|
||||||
|
{
|
||||||
|
case EVENT_POISONBOLT_VOLLEY:
|
||||||
|
DoCast(me, SPELL_POISONBOLT_VOLLEY);
|
||||||
|
events.ScheduleEvent(EVENT_POISONBOLT_VOLLEY, 10s, 15s);
|
||||||
|
break;
|
||||||
|
case EVENT_POISON_SHOCK:
|
||||||
|
DoCast(me, SPELL_POISON_SHOCK);
|
||||||
|
events.ScheduleEvent(EVENT_POISON_SHOCK, 7s, 12s);
|
||||||
|
break;
|
||||||
|
case EVENT_RESET_PHASE:
|
||||||
|
_hitcounter = 0;
|
||||||
|
_phase = PHASE_FROST;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_phase != PHASE_GLOB)
|
||||||
|
DoMeleeAttackIfReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8 _hitcounter;
|
||||||
|
Phases _phase;
|
||||||
};
|
};
|
||||||
|
|
||||||
class npc_glob_of_viscidus : public CreatureScript
|
struct boss_glob_of_viscidus : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
boss_glob_of_viscidus(Creature* creature) : ScriptedAI(creature) { }
|
||||||
npc_glob_of_viscidus() : CreatureScript("boss_glob_of_viscidus") { }
|
|
||||||
|
|
||||||
struct npc_glob_of_viscidusAI : public ScriptedAI
|
void JustDied(Unit* /*killer*/) override
|
||||||
{
|
{
|
||||||
npc_glob_of_viscidusAI(Creature* creature) : ScriptedAI(creature) { }
|
InstanceScript* instance = me->GetInstanceScript();
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
if (Creature* viscidus = me->GetMap()->GetCreature(instance->GetGuidData(DATA_VISCIDUS)))
|
||||||
{
|
{
|
||||||
InstanceScript* Instance = me->GetInstanceScript();
|
if (BossAI* viscidusAI = dynamic_cast<BossAI*>(viscidus->GetAI()))
|
||||||
|
viscidusAI->SummonedCreatureDespawn(me);
|
||||||
|
|
||||||
if (Creature* Viscidus = me->GetMap()->GetCreature(Instance->GetGuidData(DATA_VISCIDUS)))
|
if (viscidus->IsAlive() && viscidus->GetHealthPct() < 5.0f)
|
||||||
{
|
{
|
||||||
if (BossAI* ViscidusAI = dynamic_cast<BossAI*>(Viscidus->GetAI()))
|
viscidus->SetVisible(true);
|
||||||
ViscidusAI->SummonedCreatureDespawn(me);
|
Unit::Kill(viscidus->GetVictim(), viscidus);
|
||||||
|
}
|
||||||
if (Viscidus->IsAlive() && Viscidus->GetHealthPct() < 5.0f)
|
else
|
||||||
{
|
{
|
||||||
Viscidus->SetVisible(true);
|
viscidus->SetHealth(viscidus->GetHealth() - viscidus->GetMaxHealth() / 20);
|
||||||
Unit::Kill(Viscidus->GetVictim(), Viscidus);
|
viscidus->CastSpell(viscidus, SPELL_VISCIDUS_SHRINKS);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Viscidus->SetHealth(Viscidus->GetHealth() - Viscidus->GetMaxHealth() / 20);
|
|
||||||
Viscidus->CastSpell(Viscidus, SPELL_VISCIDUS_SHRINKS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MovementInform(uint32 /*type*/, uint32 id) override
|
void MovementInform(uint32 /*type*/, uint32 id) override
|
||||||
{
|
|
||||||
if (id == ROOM_CENTER)
|
|
||||||
{
|
|
||||||
DoCast(me, SPELL_REJOIN_VISCIDUS);
|
|
||||||
if (TempSummon* summon = me->ToTempSummon())
|
|
||||||
summon->UnSummon();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
{
|
||||||
return GetTempleOfAhnQirajAI<npc_glob_of_viscidusAI>(creature);
|
if (id == ROOM_CENTER)
|
||||||
|
{
|
||||||
|
DoCast(me, SPELL_REJOIN_VISCIDUS);
|
||||||
|
if (TempSummon* summon = me->ToTempSummon())
|
||||||
|
summon->UnSummon();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_viscidus()
|
void AddSC_boss_viscidus()
|
||||||
{
|
{
|
||||||
new boss_viscidus();
|
RegisterTempleOfAhnQirajCreatureAI(boss_viscidus);
|
||||||
new npc_glob_of_viscidus();
|
RegisterTempleOfAhnQirajCreatureAI(boss_glob_of_viscidus);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,4 +75,6 @@ inline AI* GetTempleOfAhnQirajAI(T* obj)
|
|||||||
return GetInstanceAI<AI>(obj, TempleOfAhnQirajScriptName);
|
return GetInstanceAI<AI>(obj, TempleOfAhnQirajScriptName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RegisterTempleOfAhnQirajCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetTempleOfAhnQirajAI)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user