script zones

This commit is contained in:
bash
2026-01-07 13:53:49 +01:00
parent 5a1445a0dc
commit ae2af138e2
14 changed files with 381 additions and 600 deletions

View File

@@ -37,15 +37,7 @@ enum Misc
NPC_DRAKKARI_SCYTHECLAW = 26628,
NPC_DRAKKARI_GUTRIPPER = 26641,
SAY_CLAW_EMOTE = 0,
EVENT_SPELL_BELLOWING_ROAR = 1,
EVENT_SPELL_GRIEVOUS_BITE = 2,
EVENT_SPELL_MANGLING_SLASH = 3,
EVENT_SPELL_FEARSOME_ROAR = 4,
EVENT_SPELL_PIERCING_SLASH = 5,
EVENT_SPELL_RAPTOR_CALL = 6,
EVENT_MENACING_CLAW = 7
SAY_CLAW_EMOTE = 0
};
class boss_dred : public CreatureScript
@@ -60,14 +52,52 @@ public:
struct boss_dredAI : public BossAI
{
boss_dredAI(Creature* creature) : BossAI(creature, DATA_DRED)
{
}
boss_dredAI(Creature* creature) : BossAI(creature, DATA_DRED) { }
void Reset() override
{
BossAI::Reset();
_raptorCount = 0;
ScheduleHealthCheckEvent({ 67, 34 }, [&] {
DoCastAOE(SPELL_BELLOWING_ROAR);
}, false);
}
void ScheduleTasks() override
{
ScheduleTimedEvent(20s, [&] {
DoCastVictim(SPELL_GRIEVOUS_BITE);
}, 20s);
ScheduleTimedEvent(18s + 500ms, [&] {
DoCastVictim(SPELL_MANGLING_SLASH);
}, 20s);
ScheduleTimedEvent(10s, 20s, [&] {
DoCastAOE(SPELL_FEARSOME_ROAR);
}, 17s);
ScheduleTimedEvent(17s, [&] {
DoCastVictim(SPELL_PIERCING_SLASH);
}, 20s);
if (IsHeroic())
{
ScheduleTimedEvent(16s, [&] {
DoCastSelf(SPELL_RAPTOR_CALL);
}, 30s);
ScheduleTimedEvent(21s, [&] {
Talk(SAY_CLAW_EMOTE);
me->setAttackTimer(BASE_ATTACK, 2000);
me->AttackerStateUpdate(me->GetVictim());
if (me->GetVictim())
me->AttackerStateUpdate(me->GetVictim());
if (me->GetVictim())
me->AttackerStateUpdate(me->GetVictim());
}, 20s);
}
}
uint32 GetData(uint32 data) const override
@@ -87,67 +117,6 @@ public:
{
BossAI::JustEngagedWith(who);
_raptorCount = 0;
events.ScheduleEvent(EVENT_SPELL_BELLOWING_ROAR, 33s);
events.ScheduleEvent(EVENT_SPELL_GRIEVOUS_BITE, 20s);
events.ScheduleEvent(EVENT_SPELL_MANGLING_SLASH, 18s + 500ms);
events.ScheduleEvent(EVENT_SPELL_FEARSOME_ROAR, 10s, 20s);
events.ScheduleEvent(EVENT_SPELL_PIERCING_SLASH, 17s);
if (IsHeroic())
{
events.ScheduleEvent(EVENT_MENACING_CLAW, 21s);
events.ScheduleEvent(EVENT_SPELL_RAPTOR_CALL, 20s, 25s);
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_SPELL_BELLOWING_ROAR:
me->CastSpell(me, SPELL_BELLOWING_ROAR, false);
events.ScheduleEvent(EVENT_SPELL_BELLOWING_ROAR, 40s);
break;
case EVENT_SPELL_GRIEVOUS_BITE:
me->CastSpell(me->GetVictim(), SPELL_GRIEVOUS_BITE, false);
events.ScheduleEvent(EVENT_SPELL_GRIEVOUS_BITE, 20s);
break;
case EVENT_SPELL_MANGLING_SLASH:
me->CastSpell(me->GetVictim(), SPELL_MANGLING_SLASH, false);
events.ScheduleEvent(EVENT_SPELL_MANGLING_SLASH, 20s);
break;
case EVENT_SPELL_FEARSOME_ROAR:
me->CastSpell(me, SPELL_FEARSOME_ROAR, false);
events.ScheduleEvent(EVENT_SPELL_FEARSOME_ROAR, 17s);
break;
case EVENT_SPELL_PIERCING_SLASH:
me->CastSpell(me->GetVictim(), SPELL_PIERCING_SLASH, false);
events.ScheduleEvent(EVENT_SPELL_PIERCING_SLASH, 20s);
break;
case EVENT_SPELL_RAPTOR_CALL:
me->CastSpell(me, SPELL_RAPTOR_CALL, false);
events.ScheduleEvent(EVENT_SPELL_RAPTOR_CALL, 20s);
break;
case EVENT_MENACING_CLAW:
Talk(SAY_CLAW_EMOTE);
me->setAttackTimer(BASE_ATTACK, 2000);
me->AttackerStateUpdate(me->GetVictim());
if (me->GetVictim())
me->AttackerStateUpdate(me->GetVictim());
if (me->GetVictim())
me->AttackerStateUpdate(me->GetVictim());
events.ScheduleEvent(EVENT_MENACING_CLAW, 20s);
break;
}
DoMeleeAttackIfReady();
}
private:
@@ -181,7 +150,23 @@ class spell_dred_raptor_call : public SpellScript
void HandleDummy(SpellEffIndex /*effIndex*/)
{
GetCaster()->SummonCreature(RAND(NPC_DRAKKARI_GUTRIPPER, NPC_DRAKKARI_SCYTHECLAW), -522.02f, -718.89f, 30.26f, 2.41f);
std::list<Creature*> raptors;
GetCaster()->GetCreatureListWithEntryInGrid(raptors, { NPC_DRAKKARI_SCYTHECLAW, NPC_DRAKKARI_GUTRIPPER }, 100.0f);
raptors.remove_if([](Creature* raptor)
{
return !raptor->IsAlive() || raptor->IsInCombat();
});
if (raptors.empty())
return;
Creature* raptor = Acore::Containers::SelectRandomContainerElement(raptors);
if (!raptor)
return;
if (GetCaster()->GetVictim())
raptor->AI()->AttackStart(GetCaster()->GetVictim());
}
void Register() override
@@ -193,16 +178,14 @@ class spell_dred_raptor_call : public SpellScript
class achievement_better_off_dred : public AchievementCriteriaScript
{
public:
achievement_better_off_dred() : AchievementCriteriaScript("achievement_better_off_dred")
{
}
achievement_better_off_dred() : AchievementCriteriaScript("achievement_better_off_dred") { }
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
if (!target)
return false;
return target->GetAI()->GetData(target->GetEntry());
return target->GetAI()->GetData(target->GetEntry()) >= 6;
}
};

View File

@@ -47,7 +47,7 @@ enum Spells
SPELL_COPY_OF_SUMMON_MINIONS = 59933,
SPELL_BLIZZARD = 49034,
SPELL_FROSTBOLT = 49037,
SPELL_TOUCH_OF_MISERY = 50090
SPELL_WRATH_OF_MISERY = 50089
};
enum Misc
@@ -56,14 +56,7 @@ enum Misc
NPC_CRYSTAL_HANDLER = 26627,
NPC_SUMMON_CRYSTAL_HANDLER_TARGET = 27583,
EVENT_SUMMON_FETID_TROLL = 1,
EVENT_SUMMON_SHADOWCASTER = 2,
EVENT_SUMMON_HULKING_CORPSE = 3,
EVENT_SUMMON_CRYSTAL_HANDLER = 4,
EVENT_CAST_OFFENSIVE_SPELL = 5,
EVENT_KILL_TALK = 6,
EVENT_CHECK_PHASE = 7,
EVENT_SPELL_SUMMON_MINIONS = 8,
EVENT_KILL_TALK = 1,
ROOM_RIGHT = 0,
ROOM_LEFT = 1,
@@ -77,198 +70,215 @@ std::unordered_map<uint32, std::tuple <uint32, Position>> const npcSummon =
{ ROOM_STAIRS, { NPC_CRYSTAL_CHANNEL_TARGET, { -378.40f, -813.13f, 59.74f, 0.0f } } },
};
class boss_novos : public CreatureScript
// 26631
struct boss_novos : public BossAI
{
public:
boss_novos() : CreatureScript("boss_novos") { }
boss_novos(Creature* creature) : BossAI(creature, DATA_NOVOS) { }
struct boss_novosAI : public BossAI
void Reset() override
{
boss_novosAI(Creature* creature) : BossAI(creature, DATA_NOVOS)
{
}
BossAI::Reset();
instance->SetBossState(DATA_NOVOS_CRYSTALS, IN_PROGRESS);
instance->SetBossState(DATA_NOVOS_CRYSTALS, NOT_STARTED);
_crystalCounter = 0;
_summonTargetRightGUID.Clear();
_summonTargetLeftGUID.Clear();
_stage = 0;
void Reset() override
{
BossAI::Reset();
instance->SetBossState(DATA_NOVOS_CRYSTALS, IN_PROGRESS);
instance->SetBossState(DATA_NOVOS_CRYSTALS, NOT_STARTED);
_crystalCounter = 0;
_summonTargetRightGUID.Clear();
_summonTargetLeftGUID.Clear();
_stage = 0;
me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE);
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE);
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
_achievement = true;
}
_achievement = true;
}
uint32 GetData(uint32 data) const override
{
if (data == me->GetEntry())
return uint32(_achievement);
return 0;
}
uint32 GetData(uint32 data) const override
{
if (data == me->GetEntry())
return uint32(_achievement);
return 0;
}
void SetData(uint32 type, uint32) override
{
if (type == me->GetEntry())
_achievement = false;
}
void SetData(uint32 type, uint32) override
{
if (type == me->GetEntry())
_achievement = false;
}
void MoveInLineOfSight(Unit* /*who*/) override { }
void MoveInLineOfSight(Unit* /*who*/) override { }
void JustEngagedWith(Unit* who) override
{
Talk(SAY_AGGRO);
BossAI::JustEngagedWith(who);
scheduler.ClearValidator();
void JustEngagedWith(Unit* who) override
{
Talk(SAY_AGGRO);
BossAI::JustEngagedWith(who);
ScheduleTimedEvent(3s, [&] {
if (Creature* trigger = summons.GetCreatureWithEntry(NPC_CRYSTAL_CHANNEL_TARGET))
trigger->CastSpell(trigger, SPELL_SUMMON_FETID_TROLL_CORPSE, true, nullptr, nullptr, me->GetGUID());
}, 3s);
events.ScheduleEvent(EVENT_SUMMON_FETID_TROLL, 3s);
events.ScheduleEvent(EVENT_SUMMON_SHADOWCASTER, 9s);
events.ScheduleEvent(EVENT_SUMMON_HULKING_CORPSE, 30s);
events.ScheduleEvent(EVENT_SUMMON_CRYSTAL_HANDLER, 20s);
events.ScheduleEvent(EVENT_CHECK_PHASE, 80s);
ScheduleTimedEvent(9s, [&] {
if (Creature* trigger = summons.GetCreatureWithEntry(NPC_CRYSTAL_CHANNEL_TARGET))
trigger->CastSpell(trigger, SPELL_SUMMON_RISEN_SHADOWCASTER, true, nullptr, nullptr, me->GetGUID());
}, 10s);
me->CastSpell(me, SPELL_ARCANE_BLAST, true);
me->CastSpell(me, SPELL_ARCANE_FIELD, true);
me->CastSpell(me, SPELL_DESPAWN_CRYSTAL_HANDLER, true);
ScheduleTimedEvent(30s, [&] {
if (Creature* trigger = summons.GetCreatureWithEntry(NPC_CRYSTAL_CHANNEL_TARGET))
trigger->CastSpell(trigger, SPELL_SUMMON_HULKING_CORPSE, true, nullptr, nullptr, me->GetGUID());
}, 30s);
for (auto& itr : npcSummon)
scheduler.Schedule(70s, [this](TaskContext context) {
if (me->HasAura(SPELL_BEAM_CHANNEL))
{
uint32 summonEntry;
Position summonPos;
std::tie(summonEntry, summonPos) = itr.second;
if (Creature* creature = me->SummonCreature(summonEntry, summonPos))
switch (itr.first)
{
case ROOM_LEFT:
_summonTargetLeftGUID = creature->GetGUID();
break;
case ROOM_RIGHT:
_summonTargetRightGUID = creature->GetGUID();
break;
}
context.Repeat(2s);
return;
}
me->SetGuidValue(UNIT_FIELD_TARGET, ObjectGuid::Empty);
me->RemoveAllAuras();
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
}
scheduler.CancelAll();
void JustDied(Unit* killer) override
{
Talk(SAY_DEATH);
BossAI::JustDied(killer);
instance->SetBossState(DATA_NOVOS_CRYSTALS, DONE);
}
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
me->InterruptNonMeleeSpells(false);
void KilledUnit(Unit* /*victim*/) override
{
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
scheduler.SetValidator([this] {
return !me->HasUnitState(UNIT_STATE_CASTING);
});
ScheduleTimedEvent(5s, 10s, [&] {
DoCastRandomTarget(SPELL_BLIZZARD);
}, 12s, 25s);
ScheduleTimedEvent(5s, 10s, [&] {
DoCastRandomTarget(SPELL_WRATH_OF_MISERY);
}, 8s, 16s);
if (IsHeroic())
{
Talk(SAY_KILL);
events.ScheduleEvent(EVENT_KILL_TALK, 6s);
ScheduleTimedEvent(10s, [&] {
DoCastAOE(SPELL_SUMMON_MINIONS);
}, 37s, 55s);
}
});
for (Seconds timer : { 16s, 32s, 48s, 64s })
{
me->m_Events.AddEventAtOffset([&] {
Talk(SAY_SUMMONING_ADDS);
Talk(EMOTE_SUMMONING_ADDS);
if (Creature* target = ObjectAccessor::GetCreature(*me, _stage ? _summonTargetLeftGUID : _summonTargetRightGUID))
target->CastSpell(target, SPELL_SUMMON_CRYSTAL_HANDLER, true, nullptr, nullptr, me->GetGUID());
_stage = _stage ? 0 : 1;
}, timer);
}
void JustSummoned(Creature* summon) override
me->SetGuidValue(UNIT_FIELD_TARGET, ObjectGuid::Empty);
me->RemoveAllAuras();
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
DoCastSelf(SPELL_ARCANE_BLAST, true);
DoCastSelf(SPELL_ARCANE_FIELD, true);
DoCastSelf(SPELL_DESPAWN_CRYSTAL_HANDLER, true);
for (auto& itr : npcSummon)
{
summons.Summon(summon);
if (me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE) && summon->GetEntry() != NPC_CRYSTAL_CHANNEL_TARGET && summon->GetEntry() != NPC_CRYSTAL_HANDLER)
uint32 summonEntry;
Position summonPos;
std::tie(summonEntry, summonPos) = itr.second;
if (Creature* creature = me->SummonCreature(summonEntry, summonPos))
switch (itr.first)
{
case ROOM_LEFT:
_summonTargetLeftGUID = creature->GetGUID();
break;
case ROOM_RIGHT:
_summonTargetRightGUID = creature->GetGUID();
break;
}
}
}
void JustDied(Unit* killer) override
{
Talk(SAY_DEATH);
BossAI::JustDied(killer);
instance->SetBossState(DATA_NOVOS_CRYSTALS, DONE);
}
void KilledUnit(Unit* /*victim*/) override
{
if (!events.HasTimeUntilEvent(EVENT_KILL_TALK))
{
Talk(SAY_KILL);
events.ScheduleEvent(EVENT_KILL_TALK, 6s);
}
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
// Phase 1
if (me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE))
{
if (summon->GetEntry() != NPC_CRYSTAL_CHANNEL_TARGET && summon->GetEntry() != NPC_CRYSTAL_HANDLER)
summon->SetReactState(REACT_DEFENSIVE);
else if (summon->GetEntry() != NPC_CRYSTAL_CHANNEL_TARGET)
if (summon->GetEntry() == NPC_FETID_TROLL_CORPSE)
summon->GetMotionMaster()->MovePoint(1, -373.56f, -770.86f, 28.59f);
if (summon->EntryEquals(NPC_CRYSTAL_HANDLER))
summon->SetInCombatWithZone();
}
// Phase 2
else if (summon->GetEntry() != NPC_CRYSTAL_CHANNEL_TARGET)
summon->SetInCombatWithZone();
}
void UpdateAI(uint32 diff) override
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
{
if (summon->GetEntry() == NPC_FETID_TROLL_CORPSE)
summon->DespawnOrUnsummon(10s);
}
void SummonMovementInform(Creature* summon, uint32 movementType, uint32 pathId) override
{
if (movementType == POINT_MOTION_TYPE && pathId == 1)
{
if (!UpdateVictim())
return;
events.Update(diff);
switch (events.ExecuteEvent())
if (summon->GetEntry() == NPC_FETID_TROLL_CORPSE)
{
case EVENT_SUMMON_FETID_TROLL:
if (Creature* trigger = summons.GetCreatureWithEntry(NPC_CRYSTAL_CHANNEL_TARGET))
trigger->CastSpell(trigger, SPELL_SUMMON_FETID_TROLL_CORPSE, true, nullptr, nullptr, me->GetGUID());
events.ScheduleEvent(EVENT_SUMMON_FETID_TROLL, 3s);
break;
case EVENT_SUMMON_HULKING_CORPSE:
if (Creature* trigger = summons.GetCreatureWithEntry(NPC_CRYSTAL_CHANNEL_TARGET))
trigger->CastSpell(trigger, SPELL_SUMMON_HULKING_CORPSE, true, nullptr, nullptr, me->GetGUID());
events.ScheduleEvent(EVENT_SUMMON_HULKING_CORPSE, 30s);
break;
case EVENT_SUMMON_SHADOWCASTER:
if (Creature* trigger = summons.GetCreatureWithEntry(NPC_CRYSTAL_CHANNEL_TARGET))
trigger->CastSpell(trigger, SPELL_SUMMON_RISEN_SHADOWCASTER, true, nullptr, nullptr, me->GetGUID());
events.ScheduleEvent(EVENT_SUMMON_SHADOWCASTER, 10s);
break;
case EVENT_SUMMON_CRYSTAL_HANDLER:
if (_crystalCounter++ < 4)
{
Talk(SAY_SUMMONING_ADDS);
Talk(EMOTE_SUMMONING_ADDS);
if (Creature* target = ObjectAccessor::GetCreature(*me, _stage ? _summonTargetLeftGUID : _summonTargetRightGUID))
target->CastSpell(target, SPELL_SUMMON_CRYSTAL_HANDLER, true, nullptr, nullptr, me->GetGUID());
_stage = _stage ? 0 : 1;
events.ScheduleEvent(EVENT_SUMMON_CRYSTAL_HANDLER, 20s);
}
break;
case EVENT_CHECK_PHASE:
if (me->HasAura(SPELL_BEAM_CHANNEL))
{
events.ScheduleEvent(EVENT_CHECK_PHASE, 2s);
break;
}
events.Reset();
events.ScheduleEvent(EVENT_CAST_OFFENSIVE_SPELL, 3s);
events.ScheduleEvent(EVENT_SPELL_SUMMON_MINIONS, 10s);
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->InterruptNonMeleeSpells(false);
break;
case EVENT_CAST_OFFENSIVE_SPELL:
if (!me->HasUnitState(UNIT_STATE_CASTING))
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
me->CastSpell(target, RAND(SPELL_BLIZZARD, SPELL_FROSTBOLT, SPELL_TOUCH_OF_MISERY), false);
events.ScheduleEvent(EVENT_CAST_OFFENSIVE_SPELL, 500ms);
break;
case EVENT_SPELL_SUMMON_MINIONS:
if (me->HasUnitState(UNIT_STATE_CASTING))
{
me->CastSpell(me, SPELL_SUMMON_MINIONS, false);
events.ScheduleEvent(EVENT_SPELL_SUMMON_MINIONS, 15s);
break;
}
events.ScheduleEvent(EVENT_SPELL_SUMMON_MINIONS, 500ms);
break;
DoZoneInCombat(summon);
_achievement = false;
}
}
bool CheckEvadeIfOutOfCombatArea() const override
{
return !SelectTargetFromPlayerList(80.0f);
}
private:
uint8 _crystalCounter;
uint8 _stage;
ObjectGuid _summonTargetRightGUID;
ObjectGuid _summonTargetLeftGUID;
bool _achievement;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetDraktharonKeepAI<boss_novosAI>(creature);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
scheduler.Update(diff);
events.Update(diff);
if (!me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE))
DoSpellAttackIfReady(SPELL_FROSTBOLT);
}
bool CheckEvadeIfOutOfCombatArea() const override
{
return !SelectTargetFromPlayerList(80.0f);
}
private:
uint8 _crystalCounter;
uint8 _stage;
ObjectGuid _summonTargetRightGUID;
ObjectGuid _summonTargetLeftGUID;
bool _achievement;
};
// 51403
class spell_novos_despawn_crystal_handler : public SpellScript
{
PrepareSpellScript(spell_novos_despawn_crystal_handler);
@@ -290,6 +300,7 @@ class spell_novos_despawn_crystal_handler : public SpellScript
}
};
// 47336
class spell_novos_crystal_handler_death_aura : public AuraScript
{
PrepareAuraScript(spell_novos_crystal_handler_death_aura);
@@ -307,6 +318,7 @@ class spell_novos_crystal_handler_death_aura : public AuraScript
}
};
// 59910
class spell_novos_summon_minions : public SpellScript
{
PrepareSpellScript(spell_novos_summon_minions);
@@ -328,6 +340,7 @@ class spell_novos_summon_minions : public SpellScript
}
};
// 2057
class achievement_oh_novos : public AchievementCriteriaScript
{
public:
@@ -341,7 +354,7 @@ public:
void AddSC_boss_novos()
{
new boss_novos();
RegisterCreatureAIWithFactory(boss_novos, GetDraktharonKeepAI);
RegisterSpellScript(spell_novos_despawn_crystal_handler);
RegisterSpellScript(spell_novos_crystal_handler_death_aura);
RegisterSpellScript(spell_novos_summon_minions);

View File

@@ -39,6 +39,7 @@ enum Creatures
NPC_KURZEL = 26664,
NPC_DRAKKARI_GUARDIAN = 26620,
NPC_RISEN_DRAKKARI_WARRIOR = 26635,
NPC_FETID_TROLL_CORPSE = 27598,
};
enum GameObjects

View File

@@ -31,50 +31,39 @@ DoorData const doorData[] =
{ 0, 0, DOOR_TYPE_ROOM }
};
class instance_drak_tharon_keep : public InstanceMapScript
struct instance_drak_tharon_keep : public InstanceScript
{
public:
instance_drak_tharon_keep() : InstanceMapScript("instance_drak_tharon_keep", MAP_DRAK_THARON_KEEP) { }
struct instance_drak_tharon_keep_InstanceScript : public InstanceScript
instance_drak_tharon_keep(Map* map) : InstanceScript(map)
{
instance_drak_tharon_keep_InstanceScript(Map* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
SetBossNumber(MAX_ENCOUNTERS);
LoadDoorData(doorData);
}
SetHeaders(DataHeader);
SetBossNumber(MAX_ENCOUNTERS);
LoadDoorData(doorData);
}
void OnGameObjectCreate(GameObject* go) override
{
switch (go->GetEntry())
{
case GO_NOVOS_CRYSTAL_1:
case GO_NOVOS_CRYSTAL_2:
case GO_NOVOS_CRYSTAL_3:
case GO_NOVOS_CRYSTAL_4:
AddDoor(go);
break;
}
}
void OnGameObjectRemove(GameObject* go) override
{
switch (go->GetEntry())
{
case GO_NOVOS_CRYSTAL_1:
case GO_NOVOS_CRYSTAL_2:
case GO_NOVOS_CRYSTAL_3:
case GO_NOVOS_CRYSTAL_4:
RemoveDoor(go);
break;
}
}
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
void OnGameObjectCreate(GameObject* go) override
{
return new instance_drak_tharon_keep_InstanceScript(map);
switch (go->GetEntry())
{
case GO_NOVOS_CRYSTAL_1:
case GO_NOVOS_CRYSTAL_2:
case GO_NOVOS_CRYSTAL_3:
case GO_NOVOS_CRYSTAL_4:
AddDoor(go);
break;
}
}
void OnGameObjectRemove(GameObject* go) override
{
switch (go->GetEntry())
{
case GO_NOVOS_CRYSTAL_1:
case GO_NOVOS_CRYSTAL_2:
case GO_NOVOS_CRYSTAL_3:
case GO_NOVOS_CRYSTAL_4:
RemoveDoor(go);
break;
}
}
};
@@ -121,7 +110,7 @@ class spell_dtk_summon_random_drakkari : public SpellScript
void AddSC_instance_drak_tharon_keep()
{
new instance_drak_tharon_keep();
RegisterInstanceScript(instance_drak_tharon_keep, MAP_DRAK_THARON_KEEP);
RegisterSpellScript(spell_dtk_raise_dead_aura);
RegisterSpellScript(spell_dtk_summon_random_drakkari);
}

View File

@@ -63,23 +63,27 @@ public:
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
}
void OnCreatureCreate(Creature* pCreature) override
void OnCreatureCreate(Creature* creature) override
{
switch (pCreature->GetEntry())
switch (creature->GetEntry())
{
case NPC_DRAKOS:
uiDrakosGUID = pCreature->GetGUID();
uiDrakosGUID = creature->GetGUID();
break;
case NPC_VAROS:
uiVarosGUID = pCreature->GetGUID();
uiVarosGUID = creature->GetGUID();
break;
case NPC_UROM:
uiUromGUID = pCreature->GetGUID();
uiUromGUID = creature->GetGUID();
break;
case NPC_EREGOS:
uiEregosGUID = pCreature->GetGUID();
uiEregosGUID = creature->GetGUID();
break;
}
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
if (creature->EntryEquals(NPC_AMBER_DRAKE, NPC_EMERALD_DRAKE, NPC_RUBY_DRAKE))
creature->SetFaction(FACTION_FRIENDLY); // Friendly faction to allow interaction from both factions
}
void OnGameObjectCreate(GameObject* pGo) override

View File

@@ -30,6 +30,7 @@ enum LokenSpells
SPELL_LIGHTNING_NOVA_THUNDERS = 52663,
SPELL_PULSING_SHOCKWAVE = 52961,
SPELL_PULSING_SHOCKWAVE_AURA = 59414,
// Achievement
ACHIEVEMENT_TIMELY_DEATH = 20384
@@ -49,15 +50,6 @@ enum Yells
EMOTE_NOVA = 9
};
enum LokenEvents
{
EVENT_LIGHTNING_NOVA = 1,
EVENT_SHOCKWAVE = 2,
EVENT_ARC_LIGHTNING = 3,
EVENT_CHECK_HEALTH = 4,
EVENT_AURA_REMOVE = 5
};
struct boss_loken : public BossAI
{
boss_loken(Creature* creature) : BossAI(creature, DATA_LOKEN), _introDone(false) { }
@@ -94,18 +86,49 @@ struct boss_loken : public BossAI
_introDone = true;
}
void OnAuraRemove(AuraApplication* auraApp, AuraRemoveMode /*mode*/) override
{
if (auraApp->GetBase()->GetId() == SPELL_LIGHTNING_NOVA_VISUAL)
{
me->RemoveAura(SPELL_LIGHTNING_NOVA_THUNDERS);
me->ClearUnitState(UNIT_STATE_CASTING);
me->ResumeChasingVictim();
}
}
void ScheduleTasks() override
{
me->m_Events.AddEventAtOffset([&] {
DoCastAOE(SPELL_PULSING_SHOCKWAVE_AURA, true);
me->ClearUnitState(UNIT_STATE_CASTING); // the aura above is a channeled spell, so we need this
DoCastSelf(SPELL_PULSING_SHOCKWAVE);
}, 3s);
ScheduleTimedEvent(15s, [&] {
Talk(SAY_NOVA);
Talk(EMOTE_NOVA);
DoCastSelf(SPELL_LIGHTNING_NOVA_VISUAL, true);
DoCastSelf(SPELL_LIGHTNING_NOVA_THUNDERS, true);
DoCastAOE(SPELL_LIGHTNING_NOVA);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
}, 15s);
if (IsHeroic())
{
ScheduleTimedEvent(10s, [&] {
DoCastRandomTarget(SPELL_ARC_LIGHTNING, 0, 100.0f, false);
}, 12s);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_TIMELY_DEATH);
}
}
void JustEngagedWith(Unit*) override
{
me->m_Events.KillAllEvents(false);
_JustEngagedWith();
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_ARC_LIGHTNING, 10s);
events.ScheduleEvent(EVENT_SHOCKWAVE, 3s);
events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 15s);
if (IsHeroic())
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_TIMELY_DEATH);
}
void JustDied(Unit*) override
@@ -122,46 +145,6 @@ struct boss_loken : public BossAI
Talk(SAY_SLAY);
}
void UpdateAI(uint32 diff) override
{
//Return since we have no target
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_LIGHTNING_NOVA:
Talk(SAY_NOVA);
events.Repeat(15s);
me->CastSpell(me, SPELL_LIGHTNING_NOVA_VISUAL, true);
me->CastSpell(me, SPELL_LIGHTNING_NOVA_THUNDERS, true);
events.DelayEvents(5s);
events.ScheduleEvent(EVENT_AURA_REMOVE, me->GetMap()->IsHeroic() ? 4s : 5s);
me->CastSpell(me, SPELL_LIGHTNING_NOVA, false);
break;
case EVENT_SHOCKWAVE:
me->CastSpell(me, SPELL_PULSING_SHOCKWAVE, false);
break;
case EVENT_ARC_LIGHTNING:
if (Unit* target = SelectTargetFromPlayerList(100, SPELL_ARC_LIGHTNING))
me->CastSpell(target, SPELL_ARC_LIGHTNING, false);
events.Repeat(12s);
break;
case EVENT_AURA_REMOVE:
me->RemoveAura(SPELL_LIGHTNING_NOVA_THUNDERS);
break;
}
DoMeleeAttackIfReady();
}
private:
bool _introDone;
};

View File

@@ -334,7 +334,6 @@ public:
SetDespawnAtEnd(false);
ResetEvent();
me->SetFaction(FACTION_FRIENDLY);
me->SetReactState(REACT_PASSIVE);
me->ReplaceAllNpcFlags(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER);
@@ -366,21 +365,12 @@ public:
case ACTION_START_ESCORT_EVENT:
Start(false, ObjectGuid::Empty, 0, true, false);
Talk(SAY_BRANN_ESCORT_START);
me->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE);
me->SetReactState(REACT_AGGRESSIVE);
me->SetRegeneratingHealth(true);
break;
case ACTION_START_TRIBUNAL:
{
me->SetReactState(REACT_PASSIVE);
Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers();
if (!PlayerList.IsEmpty())
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
me->SetFaction(i->GetSource()->GetFaction());
break;
}
SetEscortPaused(false);
InitializeEvent();
me->ReplaceAllNpcFlags(UNIT_NPC_FLAG_NONE);
@@ -394,7 +384,6 @@ public:
break;
case ACTION_GO_TO_SJONNIR:
Talk(SAY_BRANN_ENTRANCE_MEET);
me->SetFaction(FACTION_FRIENDLY);
me->SetReactState(REACT_PASSIVE);
me->SetRegeneratingHealth(true);
SetEscortPaused(false);
@@ -406,7 +395,6 @@ public:
me->SetImmuneToAll(true);
break;
case ACTION_START_SJONNIR_FIGHT:
me->SetFaction(FACTION_FRIENDLY);
SetEscortPaused(false);
break;
case ACTION_SJONNIR_DEAD:

View File

@@ -209,14 +209,14 @@ public:
enum BossIoCEvents
{
EVENT_CHECK_RAGE = 1,
EVENT_BRUTAL_STRIKE = 2,
EVENT_MORTAL_STRIKE = 2,
EVENT_CRUSHING_LEAP = 3,
EVENT_DAGGER_THROW = 4,
};
enum BossIoCSpells
{
SPELL_IOCBOSS_BRUTAL_STRIKE = 58460,
SPELL_IOCBOSS_MORTAL_STRIKE = 39171,
SPELL_IOCBOSS_CRUSHING_LEAP = 68506,
SPELL_IOCBOSS_DAGGER_THROW = 67280,
SPELL_IOCBOSS_RAGE = 66776,
@@ -262,7 +262,7 @@ public:
void JustEngagedWith(Unit* /*who*/) override
{
events.ScheduleEvent(EVENT_CHECK_RAGE, 2s);
events.ScheduleEvent(EVENT_BRUTAL_STRIKE, 6s);
events.ScheduleEvent(EVENT_MORTAL_STRIKE, 6s);
events.ScheduleEvent(EVENT_CRUSHING_LEAP, 22s);
events.ScheduleEvent(EVENT_DAGGER_THROW, 10s);
}
@@ -282,8 +282,8 @@ public:
CheckRageBuff();
events.Repeat(2s);
break;
case EVENT_BRUTAL_STRIKE:
me->CastSpell(me->GetVictim(), SPELL_IOCBOSS_BRUTAL_STRIKE, false);
case EVENT_MORTAL_STRIKE:
DoCastVictim(SPELL_IOCBOSS_MORTAL_STRIKE);
events.Repeat(6s);
break;
case EVENT_CRUSHING_LEAP:

View File

@@ -1989,6 +1989,40 @@ class spell_soul_deflection : public AuraScript
}
};
enum SpellBloodHaze
{
SPELL_BLOODSPORE_HAZE = 50380,
SPELL_PSYCHOSIS = 50396
};
// 50380 - Bloodspore Haze
class spell_bloodspore_haze : public SpellScript
{
PrepareSpellScript(spell_bloodspore_haze);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PSYCHOSIS });
}
void HandleEffectHit(SpellEffIndex /*effIndex*/)
{
if (!GetHitUnit())
return;
if (GetHitUnit()->GetAuraCount(SPELL_BLOODSPORE_HAZE) >= 5)
{
GetHitUnit()->CastSpell(GetHitUnit(), SPELL_PSYCHOSIS, true);
GetHitUnit()->RemoveAura(SPELL_BLOODSPORE_HAZE);
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_bloodspore_haze::HandleEffectHit, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
void AddSC_borean_tundra()
{
RegisterSpellScript(spell_q11919_q11940_drake_hunt_aura);
@@ -2013,4 +2047,5 @@ void AddSC_borean_tundra()
RegisterCreatureAI(npc_jenny);
RegisterSpellScript(spell_necropolis_beam);
RegisterSpellScript(spell_soul_deflection);
RegisterSpellScript(spell_bloodspore_haze);
}

View File

@@ -390,116 +390,6 @@ class spell_q12227_camera_shake : public SpellScript
OnEffectHitTarget += SpellEffectFn(spell_q12227_camera_shake::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// Tallhorn Stage
enum TallhornStage
{
//Gameobject
OBJECT_HAUNCH = 188665
};
class npc_tallhorn_stag : public CreatureScript
{
public:
npc_tallhorn_stag() : CreatureScript("npc_tallhorn_stag") { }
struct npc_tallhorn_stagAI : public ScriptedAI
{
npc_tallhorn_stagAI(Creature* creature) : ScriptedAI(creature) { }
void Reset() override
{
_phase = 1;
}
void UpdateAI(uint32 /*diff*/) override
{
if (_phase == 1)
{
if (me->FindNearestGameObject(OBJECT_HAUNCH, 2.0f))
{
me->SetStandState(UNIT_STAND_STATE_DEAD);
me->SetImmuneToPC(true);
me->ReplaceAllDynamicFlags(UNIT_DYNFLAG_DEAD);
}
_phase = 0;
}
DoMeleeAttackIfReady();
}
private:
uint8 _phase;
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_tallhorn_stagAI(creature);
}
};
// Amberpine Woodsman
enum AmberpineWoodsman
{
// Creature
NPC_TALLHORN_STAG = 26363
};
enum AmberpineWoodsmanEvents
{
EVENT_WOODSMAN_1 = 1,
EVENT_WOODSMAN_2 = 2
};
class npc_amberpine_woodsman : public CreatureScript
{
public:
npc_amberpine_woodsman() : CreatureScript("npc_amberpine_woodsman") { }
struct npc_amberpine_woodsmanAI : public ScriptedAI
{
npc_amberpine_woodsmanAI(Creature* creature) : ScriptedAI(creature) { }
void Reset() override
{
if (me->FindNearestCreature(NPC_TALLHORN_STAG, 0.2f))
{
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USE_STANDING);
}
else
_events.ScheduleEvent(EVENT_WOODSMAN_1, 0ms);
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_WOODSMAN_1:
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_LOOT);
_events.ScheduleEvent(EVENT_WOODSMAN_2, 3s);
break;
case EVENT_WOODSMAN_2:
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACK1H);
_events.ScheduleEvent(EVENT_WOODSMAN_1, 4s);
break;
default:
break;
}
}
UpdateVictim();
}
private:
EventMap _events;
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_amberpine_woodsmanAI(creature);
}
};
/*######
## Quest 12288: Overwhelmed!
@@ -1178,8 +1068,6 @@ void AddSC_grizzly_hills()
new npc_emily();
new npc_mrfloppy();
new npc_ravenous_worg();
new npc_tallhorn_stag();
new npc_amberpine_woodsman();
RegisterCreatureAI(npc_wounded_skirmisher);
RegisterSpellScript(spell_renew_skirmisher);
new npc_venture_co_straggler();

View File

@@ -49,7 +49,6 @@ class spell_q12726_song_of_wind_and_water : public SpellScript
cr->SetDisplayId(cr->GetDisplayId() == NPC_SOWAW_WATER_MODEL ? NPC_SOWAW_WIND_MODEL : NPC_SOWAW_WATER_MODEL);
if (Player* player = cr->GetCharmerOrOwnerPlayerOrPlayerItself())
{
player->KilledMonsterCredit(cr->GetDisplayId() == NPC_SOWAW_WATER_MODEL ? 29008 : 29009);
CreatureTemplate const* ct = sObjectMgr->GetCreatureTemplate(cr->GetDisplayId() == NPC_SOWAW_WIND_MODEL ? NPC_SOWAW_WIND_ELEMENTAL : NPC_SOWAW_WATER_ELEMENTAL);
for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i)
cr->m_spells[i] = ct->spells[i];
@@ -1107,108 +1106,6 @@ class spell_q12589_shoot_rjr : public SpellScript
}
};
/*######
## Quest: Reconnaissance Flight (12671)
######*/
enum ReconnaissanceFlight
{
NPC_PLANE = 28710, // Vic's Flying Machine
NPC_PILOT = 28646,
VIC_SAY_0 = 0,
VIC_SAY_1 = 1,
VIC_SAY_2 = 2,
VIC_SAY_3 = 3,
VIC_SAY_4 = 4,
VIC_SAY_5 = 5,
VIC_SAY_6 = 6,
PLANE_EMOTE = 0,
AURA_ENGINE = 52255, // Engine on Fire
SPELL_LAND = 52226, // Land Flying Machine
SPELL_CREDIT = 53328 // Land Flying Machine Credit
};
class npc_vics_flying_machine : public CreatureScript
{
public:
npc_vics_flying_machine() : CreatureScript("npc_vics_flying_machine") { }
struct npc_vics_flying_machineAI : public VehicleAI
{
npc_vics_flying_machineAI(Creature* creature) : VehicleAI(creature)
{
pointId = 0;
}
uint8 pointId;
void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply) override
{
if (apply && passenger->IsPlayer())
{
me->GetMotionMaster()->MovePath(NPC_PLANE, FORCED_MOVEMENT_NONE, PathSource::WAYPOINT_MGR);
}
}
void MovementInform(uint32 type, uint32 /*id*/) override
{
if (type != ESCORT_MOTION_TYPE)
return;
if (Vehicle* veh = me->GetVehicleKit())
if (Unit* pilot = veh->GetPassenger(0))
switch (pointId)
{
case 5:
pilot->ToCreature()->AI()->Talk(VIC_SAY_0);
break;
case 11:
pilot->ToCreature()->AI()->Talk(VIC_SAY_1);
break;
case 12:
pilot->ToCreature()->AI()->Talk(VIC_SAY_2);
break;
case 14:
pilot->ToCreature()->AI()->Talk(VIC_SAY_3);
break;
case 15:
pilot->ToCreature()->ToCreature()->AI()->Talk(VIC_SAY_4);
break;
case 17:
pilot->ToCreature()->AI()->Talk(VIC_SAY_5);
break;
case 21:
pilot->ToCreature()->AI()->Talk(VIC_SAY_6);
break;
case 25:
Talk(PLANE_EMOTE);
DoCastSelf(AURA_ENGINE);
break;
}
pointId++;
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
{
if (spell->Id == SPELL_LAND)
{
Unit* passenger = me->GetVehicleKit()->GetPassenger(1); // player should be on seat 1
if (passenger && passenger->IsPlayer())
passenger->CastSpell(passenger, SPELL_CREDIT, true);
me->DespawnOrUnsummon();
}
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_vics_flying_machineAI(creature);
}
};
/*######
## Quest Dreadsaber Mastery: Stalking the Prey (12550)
######*/
@@ -1296,7 +1193,6 @@ void AddSC_sholazar_basin()
new npc_jungle_punch_target();
RegisterSpellScript(spell_q12620_the_lifewarden_wrath);
RegisterSpellScript(spell_q12589_shoot_rjr);
new npc_vics_flying_machine();
RegisterSpellScript(spell_shango_tracks);
RegisterSpellScript(spell_q12611_deathbolt);

View File

@@ -31,6 +31,7 @@
enum qSniffingOutThePerpetrator
{
NPC_FROSTHOUND = 29677,
NPC_FROSTBITE = 29903,
SPELL_SUMMON_PURSUERS_PERIODIC = 54993,
SPELL_SNIFFING_CREDIT = 55477,
TALK_EMOTE_FROSTHOUND_SNIFF = 0,
@@ -41,7 +42,7 @@ enum qSniffingOutThePerpetrator
struct npc_frosthound : public npc_escortAI
{
explicit npc_frosthound(Creature* creature) : npc_escortAI(creature), _summons(creature) {}
explicit npc_frosthound(Creature* creature) : npc_escortAI(creature), _summons(creature), _completionWaypoint((creature->GetEntry() == NPC_FROSTBITE) ? 19 : 34) { }
void AttackStart(Unit* /*who*/) override {}
void JustEngagedWith(Unit* /*who*/) override {}
@@ -77,20 +78,15 @@ struct npc_frosthound : public npc_escortAI
if (!player)
return;
switch (waypointId)
if (waypointId == 0)
Talk(TALK_SEEN, player);
else if (waypointId == _completionWaypoint)
{
case 0:
Talk(TALK_SEEN, player);
break;
case 34:
Talk(TALK_EMOTE_TRACKED_COMPLETE, me);
Talk(TALK_CONFRONT, player);
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
summoner->ToPlayer()->KilledMonsterCredit(NPC_FROSTHOUND);
_summons.DespawnAll();
break;
default:
break;
Talk(TALK_EMOTE_TRACKED_COMPLETE, me);
Talk(TALK_CONFRONT, player);
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
summoner->ToPlayer()->KilledMonsterCredit(NPC_FROSTHOUND); // same credit for Alliance and Horde
_summons.DespawnAll();
}
}
@@ -112,6 +108,7 @@ struct npc_frosthound : public npc_escortAI
private:
SummonList _summons;
uint32 _completionWaypoint;
};
enum eIronWatcher

View File

@@ -265,6 +265,7 @@ enum OverlordDrakuru
NPC_TOTALLY_GENERIC_BUNNY = 29100,
NPC_TOTALLY_GENERIC_BUNNY_JSB = 28960,
GO_DRAKURUS_LAST_WISH = 202357,
GO_DRAKURUS_BONE = 191458,
ACTION_SUMMON_DRAKURU_LAST_WISH = 1,
ACTION_DESTROY_DRAKURU_LAST_WISH = 2,
@@ -316,7 +317,7 @@ struct npc_overlord_drakuru_betrayal : public ScriptedAI
{
npc_overlord_drakuru_betrayal(Creature* creature) : ScriptedAI(creature), _summons(me), _state(BETRAYAL_NOT_STARTED)
{
me->SetCombatMovement(false);
me->SetControlled(true, UNIT_STATE_ROOT);
}
void EnterEvadeMode(EvadeReason why) override
@@ -375,7 +376,7 @@ struct npc_overlord_drakuru_betrayal : public ScriptedAI
{
if (Player* player = who->ToPlayer())
{
bool shouldStartEvent = (_state == BETRAYAL_NOT_STARTED) && IsPlayerOnQuest(player) && player->HasAura(SPELL_SCOURGE_DISGUISE) && player->IsWithinDistInMap(me, 80.0f);
bool shouldStartEvent = (_state == BETRAYAL_NOT_STARTED) && IsPlayerOnQuest(player) && player->HasAura(SPELL_SCOURGE_DISGUISE) && player->IsWithinDistInMap(me, 80.0f) && !me->FindNearestGameObject(GO_DRAKURUS_BONE, 80.0f);
if (shouldStartEvent)
{
me->SetVisible(true);
@@ -587,6 +588,7 @@ struct npc_overlord_drakuru_betrayal : public ScriptedAI
lich->GetMotionMaster()->MovePoint(0, 6141.2393, -2011.2728, 589.8653);
break;
case EVENT_BETRAYAL_EPILOGUE_10:
_state = BETRAYAL_EVADE;
EnterEvadeMode(EVADE_REASON_OTHER);
break;
}

View File

@@ -141,13 +141,15 @@ public:
void MoveInLineOfSight(Unit* who) override
{
if (!who || me->getStandState() != UNIT_STAND_STATE_SLEEP || !who->IsPlayer() || me->GetDistance2d(who) > 90.0f || who->ToPlayer()->IsGameMaster())
if (!who || me->getStandState() != UNIT_STAND_STATE_SLEEP || !who->IsPlayer() ||
who->ToPlayer()->IsGameMaster() || me->GetDistance2d(who) > 90.0f ||
!me->isInFront(who, M_PI / 4.0f) || !me->IsWithinLOSInMap(who))
return;
me->SetInCombatWithZone();
me->SetStandState(UNIT_STAND_STATE_STAND);
ScheduleUniqueTimedEvent(5s, [&] { // 15s
ScheduleUniqueTimedEvent(5s, [&] {
me->SetStandState(UNIT_STAND_STATE_SUBMERGED);
DoCastSelf(SPELL_SUMMON_ESSENCE_OF_SUFFERING);
}, EVENT_ESSENCE_OF_SUFFERING);