mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-16 10:30:27 +00:00
refactor(Scripts/Blackmorass): Rewrite Blackmorass (#15290)
This commit is contained in:
@@ -36,131 +36,87 @@ enum Enums
|
||||
SPELL_BANISH_DRAGON_HELPER = 31550
|
||||
};
|
||||
|
||||
enum Events
|
||||
struct boss_aeonus : public BossAI
|
||||
{
|
||||
EVENT_SANDBREATH = 1,
|
||||
EVENT_TIMESTOP = 2,
|
||||
EVENT_FRENZY = 3,
|
||||
EVENT_CLEAVE = 4
|
||||
};
|
||||
boss_aeonus(Creature* creature) : BossAI(creature, DATA_AEONUS) { }
|
||||
|
||||
class boss_aeonus : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_aeonus() : CreatureScript("boss_aeonus") { }
|
||||
|
||||
struct boss_aeonusAI : public ScriptedAI
|
||||
void JustReachedHome() override
|
||||
{
|
||||
boss_aeonusAI(Creature* creature) : ScriptedAI(creature)
|
||||
if (Creature* medivh = instance->GetCreature(DATA_MEDIVH))
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
EventMap events;
|
||||
InstanceScript* instance;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
if (Unit* medivh = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_MEDIVH)))
|
||||
if (me->GetDistance2d(medivh) < 20.0f)
|
||||
me->CastSpell(me, SPELL_CORRUPT_MEDIVH, false);
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
Talk(SAY_ENTER);
|
||||
ScriptedAI::InitializeAI();
|
||||
|
||||
if (Unit* medivh = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_MEDIVH)))
|
||||
if (me->GetDistance2d(medivh) < 20.0f)
|
||||
{
|
||||
me->SetHomePosition(medivh->GetPositionX() + 14.0f * cos(medivh->GetAngle(me)), medivh->GetPositionY() + 14.0f * std::sin(medivh->GetAngle(me)), medivh->GetPositionZ(), me->GetAngle(medivh));
|
||||
me->GetMotionMaster()->MoveTargetedHome();
|
||||
DoCastAOE(SPELL_CORRUPT_MEDIVH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 5000);
|
||||
events.ScheduleEvent(EVENT_SANDBREATH, 20000);
|
||||
events.ScheduleEvent(EVENT_TIMESTOP, 15000);
|
||||
events.ScheduleEvent(EVENT_FRENZY, 30000);
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_TIME_KEEPER)
|
||||
{
|
||||
if (me->IsWithinDistInMap(who, 20.0f))
|
||||
{
|
||||
Talk(SAY_BANISH);
|
||||
me->CastSpell(me, SPELL_BANISH_DRAGON_HELPER, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
instance->SetData(TYPE_AEONUS, DONE);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_CLEAVE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_CLEAVE, false);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 10000);
|
||||
break;
|
||||
case EVENT_SANDBREATH:
|
||||
me->CastSpell(me->GetVictim(), SPELL_SAND_BREATH, false);
|
||||
events.ScheduleEvent(EVENT_SANDBREATH, 20000);
|
||||
break;
|
||||
case EVENT_TIMESTOP:
|
||||
me->CastSpell(me, SPELL_TIME_STOP, false);
|
||||
events.ScheduleEvent(EVENT_TIMESTOP, 25000);
|
||||
break;
|
||||
case EVENT_FRENZY:
|
||||
Talk(EMOTE_FRENZY);
|
||||
me->CastSpell(me, SPELL_ENRAGE, false);
|
||||
events.ScheduleEvent(EVENT_FRENZY, 30000);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void IsSummonedBy(WorldObject* /*summoner*/) override
|
||||
{
|
||||
return GetTheBlackMorassAI<boss_aeonusAI>(creature);
|
||||
Talk(SAY_ENTER);
|
||||
|
||||
if (Creature* medivh = instance->GetCreature(DATA_MEDIVH))
|
||||
{
|
||||
me->SetHomePosition(medivh->GetPositionX() + 14.0f * cos(medivh->GetAngle(me)), medivh->GetPositionY() + 14.0f * std::sin(medivh->GetAngle(me)), medivh->GetPositionZ(), me->GetAngle(medivh));
|
||||
me->GetMotionMaster()->MoveTargetedHome();
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
scheduler.Schedule(5s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
context.Repeat(10s);
|
||||
}).Schedule(20s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_SAND_BREATH);
|
||||
context.Repeat(20s);
|
||||
}).Schedule(15s, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_TIME_STOP);
|
||||
context.Repeat(25s);
|
||||
}).Schedule(30s, [this](TaskContext context)
|
||||
{
|
||||
Talk(EMOTE_FRENZY);
|
||||
DoCastSelf(SPELL_ENRAGE);
|
||||
context.Repeat(30s);
|
||||
});
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_TIME_KEEPER)
|
||||
{
|
||||
if (me->IsWithinDistInMap(who, 20.0f))
|
||||
{
|
||||
Talk(SAY_BANISH);
|
||||
DoCastAOE(SPELL_BANISH_DRAGON_HELPER, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->IsPlayer())
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_aeonus()
|
||||
{
|
||||
new boss_aeonus();
|
||||
RegisterTheBlackMorassCreatureAI(boss_aeonus);
|
||||
}
|
||||
|
||||
@@ -35,121 +35,84 @@ enum Enums
|
||||
SPELL_BANISH_DRAGON_HELPER = 31550,
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_ARCANE_BLAST = 1,
|
||||
EVENT_TIME_LAPSE = 2,
|
||||
EVENT_ARCANE_DISCHARGE = 3,
|
||||
EVENT_ATTRACTION = 4
|
||||
};
|
||||
struct boss_chrono_lord_deja : public BossAI
|
||||
{
|
||||
boss_chrono_lord_deja(Creature* creature) : BossAI(creature, DATA_CHRONO_LORD_DEJA) { }
|
||||
|
||||
class boss_chrono_lord_deja : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_chrono_lord_deja() : CreatureScript("boss_chrono_lord_deja") { }
|
||||
void OwnTalk(uint32 id)
|
||||
{
|
||||
if (me->GetEntry() == NPC_CHRONO_LORD_DEJA)
|
||||
{
|
||||
Talk(id);
|
||||
}
|
||||
}
|
||||
|
||||
struct boss_chrono_lord_dejaAI : public ScriptedAI
|
||||
{
|
||||
boss_chrono_lord_dejaAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
void InitializeAI() override
|
||||
{
|
||||
OwnTalk(SAY_ENTER);
|
||||
ScriptedAI::InitializeAI();
|
||||
}
|
||||
|
||||
EventMap events;
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
OwnTalk(SAY_AGGRO);
|
||||
_JustEngagedWith();
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
}
|
||||
scheduler.Schedule(10s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_ARCANE_BLAST);
|
||||
context.Repeat(20s);
|
||||
}).Schedule(15s, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_TIME_LAPSE);
|
||||
context.Repeat(20s);
|
||||
}).Schedule(20s, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_ARCANE_DISCHARGE);
|
||||
context.Repeat(25s);
|
||||
});
|
||||
|
||||
void OwnTalk(uint32 id)
|
||||
{
|
||||
if (me->GetEntry() == NPC_CHRONO_LORD_DEJA)
|
||||
Talk(id);
|
||||
}
|
||||
if (IsHeroic())
|
||||
{
|
||||
scheduler.Schedule(20s, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_ATTRACTION);
|
||||
context.Repeat(30s);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
OwnTalk(SAY_ENTER);
|
||||
ScriptedAI::InitializeAI();
|
||||
}
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_TIME_KEEPER)
|
||||
{
|
||||
if (me->IsWithinDistInMap(who, 20.0f))
|
||||
{
|
||||
OwnTalk(SAY_BANISH);
|
||||
DoCastAOE(SPELL_BANISH_DRAGON_HELPER);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_ARCANE_BLAST, 10000);
|
||||
events.ScheduleEvent(EVENT_TIME_LAPSE, 15000);
|
||||
events.ScheduleEvent(EVENT_ARCANE_DISCHARGE, 25000);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_ATTRACTION, 20000);
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
OwnTalk(SAY_AGGRO);
|
||||
}
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->IsPlayer())
|
||||
{
|
||||
OwnTalk(SAY_SLAY);
|
||||
}
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_TIME_KEEPER)
|
||||
{
|
||||
if (me->IsWithinDistInMap(who, 20.0f))
|
||||
{
|
||||
OwnTalk(SAY_BANISH);
|
||||
me->CastSpell(me, SPELL_BANISH_DRAGON_HELPER, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
OwnTalk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
OwnTalk(SAY_DEATH);
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
instance->SetData(TYPE_CHRONO_LORD_DEJA, DONE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_ARCANE_BLAST:
|
||||
me->CastSpell(me->GetVictim(), SPELL_ARCANE_BLAST, false);
|
||||
events.ScheduleEvent(EVENT_ARCANE_BLAST, 20000);
|
||||
break;
|
||||
case EVENT_TIME_LAPSE:
|
||||
me->CastSpell(me, SPELL_TIME_LAPSE, false);
|
||||
events.ScheduleEvent(EVENT_TIME_LAPSE, 20000);
|
||||
break;
|
||||
case EVENT_ARCANE_DISCHARGE:
|
||||
me->CastSpell(me, SPELL_ARCANE_DISCHARGE, false);
|
||||
events.ScheduleEvent(EVENT_ARCANE_DISCHARGE, 25000);
|
||||
break;
|
||||
case EVENT_ATTRACTION:
|
||||
me->CastSpell(me, SPELL_ATTRACTION, false);
|
||||
events.ScheduleEvent(EVENT_ATTRACTION, 30000);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetTheBlackMorassAI<boss_chrono_lord_dejaAI>(creature);
|
||||
}
|
||||
};
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
OwnTalk(SAY_DEATH);
|
||||
_JustDied();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_chrono_lord_deja()
|
||||
{
|
||||
new boss_chrono_lord_deja();
|
||||
RegisterTheBlackMorassCreatureAI(boss_chrono_lord_deja);
|
||||
}
|
||||
|
||||
@@ -34,121 +34,83 @@ enum Enums
|
||||
SPELL_BANISH_DRAGON_HELPER = 31550
|
||||
};
|
||||
|
||||
enum Events
|
||||
struct boss_temporus : public BossAI
|
||||
{
|
||||
EVENT_HASTEN = 1,
|
||||
EVENT_MORTAL_WOUND = 2,
|
||||
EVENT_WING_BUFFET = 3,
|
||||
EVENT_SPELL_REFLECTION = 4
|
||||
};
|
||||
boss_temporus(Creature* creature) : BossAI(creature, DATA_TEMPORUS) { }
|
||||
|
||||
class boss_temporus : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_temporus() : CreatureScript("boss_temporus") { }
|
||||
|
||||
struct boss_temporusAI : public ScriptedAI
|
||||
void OwnTalk(uint32 id)
|
||||
{
|
||||
boss_temporusAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
if (me->GetEntry() == NPC_TEMPORUS)
|
||||
Talk(id);
|
||||
}
|
||||
|
||||
EventMap events;
|
||||
|
||||
void OwnTalk(uint32 id)
|
||||
{
|
||||
if (me->GetEntry() == NPC_TEMPORUS)
|
||||
Talk(id);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
OwnTalk(SAY_ENTER);
|
||||
ScriptedAI::InitializeAI();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_HASTEN, 12000);
|
||||
events.ScheduleEvent(EVENT_MORTAL_WOUND, 5000);
|
||||
events.ScheduleEvent(EVENT_WING_BUFFET, 20000);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_SPELL_REFLECTION, 28000);
|
||||
|
||||
OwnTalk(SAY_AGGRO);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
OwnTalk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
OwnTalk(SAY_DEATH);
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
instance->SetData(TYPE_TEMPORUS, DONE);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_TIME_KEEPER)
|
||||
{
|
||||
if (me->IsWithinDistInMap(who, 20.0f))
|
||||
{
|
||||
OwnTalk(SAY_BANISH);
|
||||
me->CastSpell(me, SPELL_BANISH_DRAGON_HELPER, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_HASTEN:
|
||||
me->CastSpell(me, SPELL_HASTEN, false);
|
||||
events.ScheduleEvent(EVENT_HASTEN, 20000);
|
||||
break;
|
||||
case EVENT_MORTAL_WOUND:
|
||||
me->CastSpell(me->GetVictim(), SPELL_MORTAL_WOUND, false);
|
||||
events.ScheduleEvent(EVENT_MORTAL_WOUND, 10000);
|
||||
break;
|
||||
case EVENT_WING_BUFFET:
|
||||
me->CastSpell(me, SPELL_WING_BUFFET, false);
|
||||
events.ScheduleEvent(EVENT_WING_BUFFET, 20000);
|
||||
break;
|
||||
case EVENT_SPELL_REFLECTION:
|
||||
me->CastSpell(me, SPELL_REFLECT, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_REFLECTION, 30000);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void InitializeAI() override
|
||||
{
|
||||
return GetTheBlackMorassAI<boss_temporusAI>(creature);
|
||||
OwnTalk(SAY_ENTER);
|
||||
ScriptedAI::InitializeAI();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
|
||||
scheduler.Schedule(12s, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_HASTEN);
|
||||
context.Repeat(20s);
|
||||
}).Schedule(5s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_MORTAL_WOUND);
|
||||
context.Repeat(10s);
|
||||
}).Schedule(20s, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_WING_BUFFET);
|
||||
context.Repeat(20s);
|
||||
});
|
||||
|
||||
if (IsHeroic())
|
||||
{
|
||||
scheduler.Schedule(28s, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_REFLECT);
|
||||
context.Repeat(30s);
|
||||
});
|
||||
}
|
||||
|
||||
OwnTalk(SAY_AGGRO);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->IsPlayer())
|
||||
{
|
||||
OwnTalk(SAY_SLAY);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
OwnTalk(SAY_DEATH);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_TIME_KEEPER)
|
||||
{
|
||||
if (me->IsWithinDistInMap(who, 20.0f))
|
||||
{
|
||||
OwnTalk(SAY_BANISH);
|
||||
me->CastSpell(me, SPELL_BANISH_DRAGON_HELPER, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_temporus()
|
||||
{
|
||||
new boss_temporus();
|
||||
RegisterTheBlackMorassCreatureAI(boss_temporus);
|
||||
}
|
||||
|
||||
@@ -23,8 +23,7 @@
|
||||
#include "TemporarySummon.h"
|
||||
#include "the_black_morass.h"
|
||||
|
||||
#define MAX_PORTAL_LOCATIONS 4
|
||||
const Position PortalLocation[MAX_PORTAL_LOCATIONS] =
|
||||
const Position PortalLocation[4] =
|
||||
{
|
||||
{ -2030.8318f, 7024.9443f, 23.071817f, 3.14159f },
|
||||
{ -1961.7335f, 7029.5280f, 21.811401f, 2.12931f },
|
||||
@@ -32,6 +31,11 @@ const Position PortalLocation[MAX_PORTAL_LOCATIONS] =
|
||||
{ -1930.9106f, 7183.5970f, 23.007639f, 3.59537f }
|
||||
};
|
||||
|
||||
ObjectData const creatureData[1] =
|
||||
{
|
||||
{ NPC_MEDIVH, DATA_MEDIVH }
|
||||
};
|
||||
|
||||
class instance_the_black_morass : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
@@ -44,67 +48,172 @@ public:
|
||||
|
||||
struct instance_the_black_morass_InstanceMapScript : public InstanceScript
|
||||
{
|
||||
instance_the_black_morass_InstanceMapScript(Map* map) : InstanceScript(map) { }
|
||||
|
||||
GuidSet encounterNPCs;
|
||||
uint32 encounters[MAX_ENCOUNTER];
|
||||
ObjectGuid _medivhGUID;
|
||||
uint8 _currentRift;
|
||||
int8 _shieldPercent;
|
||||
|
||||
void Initialize() override
|
||||
instance_the_black_morass_InstanceMapScript(Map* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
memset(&encounters, 0, sizeof(encounters));
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
_currentRift = 0;
|
||||
_shieldPercent = 100;
|
||||
encounterNPCs.clear();
|
||||
_encounterNPCs.clear();
|
||||
_timerToNextBoss = 0;
|
||||
}
|
||||
|
||||
void CleanupInstance()
|
||||
{
|
||||
Events.Reset();
|
||||
_currentRift = 0;
|
||||
_shieldPercent = 100;
|
||||
|
||||
_usedRiftPostions.fill(ObjectGuid::Empty);
|
||||
_availableRiftPositions.clear();
|
||||
_scheduler.CancelAll();
|
||||
|
||||
instance->LoadGrid(-2023.0f, 7121.0f);
|
||||
if (Creature* medivh = instance->GetCreature(_medivhGUID))
|
||||
for (Position const& pos : PortalLocation)
|
||||
{
|
||||
medivh->DespawnOrUnsummon();
|
||||
medivh->SetRespawnTime(3);
|
||||
_availableRiftPositions.push_back(pos);
|
||||
}
|
||||
|
||||
GuidSet eCopy = encounterNPCs;
|
||||
for (ObjectGuid const& guid : eCopy)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon();
|
||||
instance->LoadGrid(-2023.0f, 7121.0f);
|
||||
if (Creature* medivh = GetCreature(DATA_MEDIVH))
|
||||
{
|
||||
medivh->DespawnOrUnsummon(0ms, 3s);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsEncounterInProgress() const override
|
||||
bool SetBossState(uint32 type, EncounterState state) override
|
||||
{
|
||||
return false;
|
||||
if (!InstanceScript::SetBossState(type, state))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (state == DONE)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_AEONUS:
|
||||
{
|
||||
if (Creature* medivh = GetCreature(DATA_MEDIVH))
|
||||
{
|
||||
medivh->AI()->DoAction(ACTION_OUTRO);
|
||||
}
|
||||
|
||||
instance->DoForAllPlayers([&](Player* player)
|
||||
{
|
||||
if (player->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
player->AreaExploredOrEventHappens(QUEST_OPENING_PORTAL);
|
||||
}
|
||||
|
||||
if (player->GetQuestStatus(QUEST_MASTER_TOUCH) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
player->AreaExploredOrEventHappens(QUEST_MASTER_TOUCH);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case DATA_CHRONO_LORD_DEJA:
|
||||
case DATA_TEMPORUS:
|
||||
{
|
||||
for (ObjectGuid const& guid : _encounterNPCs)
|
||||
{
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
{
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_RIFT_KEEPER_WARLOCK:
|
||||
case NPC_RIFT_KEEPER_MAGE:
|
||||
case NPC_RIFT_LORD:
|
||||
case NPC_RIFT_LORD_2:
|
||||
case NPC_TIME_RIFT:
|
||||
creature->DespawnOrUnsummon();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_timerToNextBoss || _timerToNextBoss > 30 * IN_MILLISECONDS)
|
||||
{
|
||||
ScheduleNextPortal(30s);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScheduleNextPortal(Milliseconds(_timerToNextBoss));
|
||||
}
|
||||
|
||||
_timerToNextBoss = (instance->IsHeroic() ? 300 : 150) * IN_MILLISECONDS;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnPlayerEnter(Player* player) override
|
||||
{
|
||||
if (instance->GetPlayersCountExceptGMs() <= 1 && GetData(TYPE_AEONUS) != DONE)
|
||||
if (instance->GetPlayersCountExceptGMs() <= 1 && GetBossState(DATA_AEONUS) != DONE)
|
||||
{
|
||||
CleanupInstance();
|
||||
}
|
||||
|
||||
player->SendUpdateWorldState(WORLD_STATE_BM, _currentRift > 0 ? 1 : 0);
|
||||
player->SendUpdateWorldState(WORLD_STATE_BM_SHIELD, _shieldPercent);
|
||||
player->SendUpdateWorldState(WORLD_STATE_BM_RIFT, _currentRift);
|
||||
}
|
||||
|
||||
void ScheduleNextPortal(Milliseconds time)
|
||||
{
|
||||
_scheduler.CancelGroup(CONTEXT_GROUP_RIFTS);
|
||||
|
||||
_scheduler.Schedule(time, [this](TaskContext context)
|
||||
{
|
||||
if (GetCreature(DATA_MEDIVH))
|
||||
{
|
||||
Position spawnPos;
|
||||
if (!_availableRiftPositions.empty())
|
||||
{
|
||||
spawnPos = Acore::Containers::SelectRandomContainerElement(_availableRiftPositions);
|
||||
_availableRiftPositions.remove(spawnPos);
|
||||
|
||||
DoUpdateWorldState(WORLD_STATE_BM_RIFT, ++_currentRift);
|
||||
|
||||
if (Creature* rift = instance->SummonCreature(NPC_TIME_RIFT, spawnPos))
|
||||
{
|
||||
_scheduler.Schedule(6s, [this, rift](TaskContext)
|
||||
{
|
||||
SummonPortalKeeper(rift);
|
||||
});
|
||||
}
|
||||
|
||||
// Here we check if we have available rift spots.
|
||||
// If there are spots available, spawn a rift instantly.
|
||||
if (!_availableRiftPositions.empty())
|
||||
{
|
||||
context.Repeat((_currentRift >= 13 ? 2min : 90s));
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Repeat(3s);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Repeat(3s);
|
||||
}
|
||||
|
||||
context.SetGroup(CONTEXT_GROUP_RIFTS);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_MEDIVH:
|
||||
_medivhGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_TIME_RIFT:
|
||||
case NPC_CHRONO_LORD_DEJA:
|
||||
case NPC_INFINITE_CHRONO_LORD:
|
||||
@@ -121,9 +230,11 @@ public:
|
||||
case NPC_INFINITE_EXECUTIONER:
|
||||
case NPC_INFINITE_VANQUISHER:
|
||||
case NPC_DP_BEAM_STALKER:
|
||||
encounterNPCs.insert(creature->GetGUID());
|
||||
_encounterNPCs.insert(creature->GetGUID());
|
||||
break;
|
||||
}
|
||||
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
}
|
||||
|
||||
void OnCreatureRemove(Creature* creature) override
|
||||
@@ -131,6 +242,22 @@ public:
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_TIME_RIFT:
|
||||
_availableRiftPositions.push_back(creature->GetHomePosition());
|
||||
|
||||
if (GetBossState(DATA_AEONUS) != DONE)
|
||||
{
|
||||
// Here we check if we have available rift spots.
|
||||
// If there are spots available, spawn a rift instantly.
|
||||
if (!_availableRiftPositions.empty())
|
||||
{
|
||||
ScheduleNextPortal(4s);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScheduleNextPortal((_currentRift >= 13 ? 2min : 90s));
|
||||
}
|
||||
}
|
||||
[[fallthrough]];
|
||||
case NPC_CHRONO_LORD_DEJA:
|
||||
case NPC_INFINITE_CHRONO_LORD:
|
||||
case NPC_TEMPORUS:
|
||||
@@ -145,92 +272,28 @@ public:
|
||||
case NPC_INFINITE_CRONOMANCER:
|
||||
case NPC_INFINITE_EXECUTIONER:
|
||||
case NPC_INFINITE_VANQUISHER:
|
||||
encounterNPCs.erase(creature->GetGUID());
|
||||
_encounterNPCs.erase(creature->GetGUID());
|
||||
break;
|
||||
}
|
||||
|
||||
InstanceScript::OnCreatureRemove(creature);
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TYPE_AEONUS:
|
||||
{
|
||||
encounters[type] = DONE;
|
||||
SaveToDB();
|
||||
|
||||
if (Creature* medivh = instance->GetCreature(_medivhGUID))
|
||||
{
|
||||
medivh->AI()->DoAction(ACTION_OUTRO);
|
||||
}
|
||||
|
||||
Map::PlayerList const& players = instance->GetPlayers();
|
||||
if (!players.IsEmpty())
|
||||
{
|
||||
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
|
||||
{
|
||||
if (Player* player = itr->GetSource())
|
||||
{
|
||||
if (player->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
player->AreaExploredOrEventHappens(QUEST_OPENING_PORTAL);
|
||||
}
|
||||
|
||||
if (player->GetQuestStatus(QUEST_MASTER_TOUCH) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
player->AreaExploredOrEventHappens(QUEST_MASTER_TOUCH);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TYPE_CHRONO_LORD_DEJA:
|
||||
case TYPE_TEMPORUS:
|
||||
{
|
||||
GuidSet eCopy = encounterNPCs;
|
||||
for (ObjectGuid const& guid : eCopy)
|
||||
{
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
{
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_RIFT_KEEPER_WARLOCK:
|
||||
case NPC_RIFT_KEEPER_MAGE:
|
||||
case NPC_RIFT_LORD:
|
||||
case NPC_RIFT_LORD_2:
|
||||
case NPC_TIME_RIFT:
|
||||
creature->DespawnOrUnsummon();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
encounters[type] = DONE;
|
||||
|
||||
if (!_timerToNextBoss || _timerToNextBoss > 30 * IN_MILLISECONDS)
|
||||
{
|
||||
Events.RescheduleEvent(EVENT_NEXT_PORTAL, 30 * IN_MILLISECONDS);
|
||||
}
|
||||
else
|
||||
{
|
||||
Events.RescheduleEvent(EVENT_NEXT_PORTAL, _timerToNextBoss);
|
||||
}
|
||||
Events.SetPhase(1);
|
||||
SaveToDB();
|
||||
_timerToNextBoss = (instance->IsHeroic() ? 300 : 150) * IN_MILLISECONDS;
|
||||
break;
|
||||
}
|
||||
case DATA_MEDIVH:
|
||||
{
|
||||
DoUpdateWorldState(WORLD_STATE_BM, 1);
|
||||
DoUpdateWorldState(WORLD_STATE_BM_SHIELD, _shieldPercent);
|
||||
DoUpdateWorldState(WORLD_STATE_BM_RIFT, _currentRift);
|
||||
Events.RescheduleEvent(EVENT_NEXT_PORTAL, 3000);
|
||||
|
||||
ScheduleNextPortal(3s);
|
||||
|
||||
_timerToNextBoss = (instance->IsHeroic() ? 300 : 150) * IN_MILLISECONDS;
|
||||
|
||||
for (ObjectGuid const& guid : encounterNPCs)
|
||||
for (ObjectGuid const& guid : _encounterNPCs)
|
||||
{
|
||||
if (guid.GetEntry() == NPC_DP_BEAM_STALKER)
|
||||
{
|
||||
@@ -264,26 +327,73 @@ public:
|
||||
|
||||
if (!_shieldPercent)
|
||||
{
|
||||
if (Creature* medivh = instance->GetCreature(_medivhGUID))
|
||||
if (Creature* medivh = GetCreature(DATA_MEDIVH))
|
||||
{
|
||||
if (medivh->IsAlive())
|
||||
if (medivh->IsAlive() && medivh->IsAIEnabled)
|
||||
{
|
||||
medivh->SetImmuneToNPC(true);
|
||||
medivh->AI()->Talk(SAY_MEDIVH_DEATH);
|
||||
|
||||
if (medivh->IsAIEnabled)
|
||||
{
|
||||
medivh->AI()->Talk(SAY_MEDIVH_DEATH);
|
||||
}
|
||||
|
||||
Events.ScheduleEvent(EVENT_WIPE_1, 4s);
|
||||
|
||||
for (ObjectGuid const& guid : encounterNPCs)
|
||||
for (ObjectGuid const& guid : _encounterNPCs)
|
||||
{
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
{
|
||||
creature->InterruptNonMeleeSpells(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 1 - Medivh loses all auras.
|
||||
_scheduler.Schedule(4s, [this](TaskContext)
|
||||
{
|
||||
if (Creature* medivh = GetCreature(DATA_MEDIVH))
|
||||
{
|
||||
medivh->RemoveAllAuras();
|
||||
}
|
||||
|
||||
// Step 2 - Medivh dies and visual effect NPCs are despawned.
|
||||
_scheduler.Schedule(500ms, [this](TaskContext)
|
||||
{
|
||||
if (Creature* medivh = GetCreature(DATA_MEDIVH))
|
||||
{
|
||||
medivh->KillSelf(false);
|
||||
|
||||
GuidSet encounterNPCSCopy = _encounterNPCs;
|
||||
for (ObjectGuid const& guid : encounterNPCSCopy)
|
||||
{
|
||||
switch (guid.GetEntry())
|
||||
{
|
||||
case NPC_TIME_RIFT:
|
||||
case NPC_DP_EMITTER_STALKER:
|
||||
case NPC_DP_CRYSTAL_STALKER:
|
||||
case NPC_DP_BEAM_STALKER:
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
{
|
||||
creature->DespawnOrUnsummon();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3 - All summoned creatures despawn
|
||||
_scheduler.Schedule(2s, [this](TaskContext)
|
||||
{
|
||||
GuidSet encounterNPCSCopy = _encounterNPCs;
|
||||
for (ObjectGuid const& guid : encounterNPCSCopy)
|
||||
{
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
{
|
||||
creature->CastSpell(creature, SPELL_TELEPORT_VISUAL, true);
|
||||
creature->DespawnOrUnsummon(1200ms, 0s);
|
||||
}
|
||||
}
|
||||
|
||||
_scheduler.CancelAll();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -298,10 +408,6 @@ public:
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TYPE_CHRONO_LORD_DEJA:
|
||||
case TYPE_TEMPORUS:
|
||||
case TYPE_AEONUS:
|
||||
return encounters[type];
|
||||
case DATA_SHIELD_PERCENT:
|
||||
return _shieldPercent;
|
||||
case DATA_RIFT_NUMBER:
|
||||
@@ -310,66 +416,21 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetGuidData(uint32 type, ObjectGuid data) override
|
||||
void SummonPortalKeeper(Creature* rift)
|
||||
{
|
||||
if (type == DATA_SUMMONED_NPC)
|
||||
encounterNPCs.insert(data);
|
||||
else if (type == DATA_DELETED_NPC)
|
||||
encounterNPCs.erase(data);
|
||||
else if (type == DATA_RIFT_KILLED)
|
||||
{
|
||||
if (!Events.IsInPhase(1))
|
||||
{
|
||||
uint8 emptySpots = 0;
|
||||
for (uint8 i = 0; i < MAX_PORTAL_LOCATIONS; ++i)
|
||||
{
|
||||
if (!_usedRiftPostions[i])
|
||||
{
|
||||
++emptySpots;
|
||||
}
|
||||
|
||||
if (_usedRiftPostions[i] == data)
|
||||
{
|
||||
_usedRiftPostions[i].Clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (emptySpots >= MAX_PORTAL_LOCATIONS - 1)
|
||||
{
|
||||
Events.RescheduleEvent(EVENT_NEXT_PORTAL, 4000);
|
||||
}
|
||||
else if (!emptySpots)
|
||||
{
|
||||
Events.RescheduleEvent(EVENT_NEXT_PORTAL, (_currentRift >= 13 ? 120 : 90) * IN_MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ObjectGuid GetGuidData(uint32 data) const override
|
||||
{
|
||||
if (data == DATA_MEDIVH)
|
||||
return _medivhGUID;
|
||||
|
||||
return ObjectGuid::Empty;
|
||||
}
|
||||
|
||||
void SummonPortalKeeper(uint32 eventId)
|
||||
{
|
||||
uint8 riftPosition = eventId - EVENT_SUMMON_KEEPER_1;
|
||||
ObjectGuid const& riftGUID = _usedRiftPostions[riftPosition];
|
||||
Creature* rift = instance->GetCreature(riftGUID);
|
||||
if (!rift)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int32 entry = 0;
|
||||
switch (_currentRift)
|
||||
{
|
||||
case 6:
|
||||
entry = GetData(TYPE_CHRONO_LORD_DEJA) == DONE ? (instance->IsHeroic() ? NPC_INFINITE_CHRONO_LORD : -NPC_CHRONO_LORD_DEJA) : NPC_CHRONO_LORD_DEJA;
|
||||
entry = GetBossState(DATA_CHRONO_LORD_DEJA) == DONE ? (instance->IsHeroic() ? NPC_INFINITE_CHRONO_LORD : -NPC_CHRONO_LORD_DEJA) : NPC_CHRONO_LORD_DEJA;
|
||||
break;
|
||||
case 12:
|
||||
entry = GetData(TYPE_TEMPORUS) == DONE ? (instance->IsHeroic() ? NPC_INFINITE_TIMEREAVER : -NPC_TEMPORUS) : NPC_TEMPORUS;
|
||||
entry = GetBossState(DATA_TEMPORUS) == DONE ? (instance->IsHeroic() ? NPC_INFINITE_TIMEREAVER : -NPC_TEMPORUS) : NPC_TEMPORUS;
|
||||
break;
|
||||
case 18:
|
||||
entry = NPC_AEONUS;
|
||||
@@ -381,21 +442,22 @@ public:
|
||||
|
||||
Position pos = rift->GetNearPosition(10.0f, 2 * M_PI * rand_norm());
|
||||
|
||||
if (TempSummon* summon = instance->SummonCreature(std::abs(entry), pos))
|
||||
if (Creature* summon = rift->SummonCreature(std::abs(entry), pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3 * MINUTE * IN_MILLISECONDS))
|
||||
{
|
||||
summon->SetTempSummonType(TEMPSUMMON_CORPSE_TIMED_DESPAWN);
|
||||
summon->SetTimer(3 * MINUTE * IN_MILLISECONDS);
|
||||
|
||||
if (entry < 0)
|
||||
{
|
||||
summon->SetLootMode(0);
|
||||
}
|
||||
|
||||
if (summon->GetEntry() != NPC_AEONUS)
|
||||
{
|
||||
rift->AI()->SetGUID(summon->GetGUID());
|
||||
rift->CastSpell(summon, SPELL_RIFT_CHANNEL, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
summon->SetReactState(REACT_DEFENSIVE);
|
||||
_scheduler.CancelGroup(CONTEXT_GROUP_RIFTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,130 +475,16 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
Events.Update(diff);
|
||||
|
||||
uint32 eventId = Events.ExecuteEvent();
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_NEXT_PORTAL:
|
||||
{
|
||||
if (instance->GetCreature(_medivhGUID))
|
||||
{
|
||||
uint8 position = MAX_PORTAL_LOCATIONS;
|
||||
|
||||
std::vector<uint8> possibleSpots;
|
||||
for (uint8 i = 0; i < MAX_PORTAL_LOCATIONS; ++i)
|
||||
{
|
||||
if (!_usedRiftPostions[i])
|
||||
{
|
||||
possibleSpots.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!possibleSpots.empty())
|
||||
{
|
||||
position = Acore::Containers::SelectRandomContainerElement(possibleSpots);
|
||||
}
|
||||
|
||||
if (position < MAX_PORTAL_LOCATIONS)
|
||||
{
|
||||
++_currentRift;
|
||||
DoUpdateWorldState(WORLD_STATE_BM_RIFT, _currentRift);
|
||||
Events.ScheduleEvent(EVENT_SUMMON_KEEPER_1 + position, 6000);
|
||||
Events.SetPhase(0);
|
||||
|
||||
if (Creature* rift = instance->SummonCreature(NPC_TIME_RIFT, PortalLocation[position]))
|
||||
{
|
||||
_usedRiftPostions[position] = rift->GetGUID();
|
||||
|
||||
for (uint8 i = 0; i < MAX_PORTAL_LOCATIONS; ++i)
|
||||
{
|
||||
if (!_usedRiftPostions[i])
|
||||
{
|
||||
Events.RescheduleEvent(EVENT_NEXT_PORTAL, (_currentRift >= 13 ? 120 : 90) * IN_MILLISECONDS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EVENT_SUMMON_KEEPER_1:
|
||||
case EVENT_SUMMON_KEEPER_2:
|
||||
case EVENT_SUMMON_KEEPER_3:
|
||||
case EVENT_SUMMON_KEEPER_4:
|
||||
SummonPortalKeeper(eventId);
|
||||
break;
|
||||
case EVENT_WIPE_1:
|
||||
if (Creature* medivh = instance->GetCreature(_medivhGUID))
|
||||
{
|
||||
medivh->RemoveAllAuras();
|
||||
}
|
||||
Events.ScheduleEvent(EVENT_WIPE_2, 500ms);
|
||||
break;
|
||||
case EVENT_WIPE_2:
|
||||
if (Creature* medivh = instance->GetCreature(_medivhGUID))
|
||||
{
|
||||
medivh->KillSelf(false);
|
||||
|
||||
GuidSet encounterNPCSCopy = encounterNPCs;
|
||||
for (ObjectGuid const& guid : encounterNPCSCopy)
|
||||
{
|
||||
switch (guid.GetEntry())
|
||||
{
|
||||
case NPC_TIME_RIFT:
|
||||
case NPC_DP_EMITTER_STALKER:
|
||||
case NPC_DP_CRYSTAL_STALKER:
|
||||
case NPC_DP_BEAM_STALKER:
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
{
|
||||
creature->DespawnOrUnsummon();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Events.ScheduleEvent(EVENT_WIPE_3, 2s);
|
||||
break;
|
||||
case EVENT_WIPE_3:
|
||||
{
|
||||
GuidSet encounterNPCSCopy = encounterNPCs;
|
||||
for (ObjectGuid const& guid : encounterNPCSCopy)
|
||||
{
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
{
|
||||
creature->CastSpell(creature, SPELL_TELEPORT_VISUAL, true);
|
||||
creature->DespawnOrUnsummon(1200ms, 0s);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ReadSaveDataMore(std::istringstream& data) override
|
||||
{
|
||||
data >> encounters[0];
|
||||
data >> encounters[1];
|
||||
data >> encounters[2];
|
||||
}
|
||||
|
||||
void WriteSaveDataMore(std::ostringstream& data) override
|
||||
{
|
||||
data << encounters[0] << ' '
|
||||
<< encounters[1] << ' '
|
||||
<< encounters[2] << ' ';
|
||||
_scheduler.Update();
|
||||
}
|
||||
|
||||
protected:
|
||||
EventMap Events;
|
||||
std::array<ObjectGuid, MAX_PORTAL_LOCATIONS> _usedRiftPostions;
|
||||
std::list<Position> _availableRiftPositions;
|
||||
uint32 _timerToNextBoss;
|
||||
GuidSet _encounterNPCs;
|
||||
uint8 _currentRift;
|
||||
int8 _shieldPercent;
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ struct npc_medivh_bm : public ScriptedAI
|
||||
events.Reset();
|
||||
me->CastSpell(me, SPELL_MANA_SHIELD, true);
|
||||
|
||||
if (_instance->GetData(TYPE_AEONUS) != DONE)
|
||||
if (_instance->GetBossState(DATA_AEONUS) != DONE)
|
||||
{
|
||||
me->CastSpell(me, SPELL_MEDIVH_CHANNEL, false);
|
||||
}
|
||||
@@ -101,8 +101,6 @@ struct npc_medivh_bm : public ScriptedAI
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
_instance->SetGuidData(DATA_SUMMONED_NPC, summon->GetGUID());
|
||||
|
||||
if (summon->GetEntry() == NPC_DP_CRYSTAL_STALKER)
|
||||
{
|
||||
summon->DespawnOrUnsummon(25000);
|
||||
@@ -119,14 +117,9 @@ struct npc_medivh_bm : public ScriptedAI
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* summon) override
|
||||
{
|
||||
_instance->SetGuidData(DATA_DELETED_NPC, summon->GetGUID());
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (!events.Empty() || _instance->GetData(TYPE_AEONUS) == DONE)
|
||||
if (!events.Empty() || _instance->GetBossState(DATA_AEONUS) == DONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -274,9 +267,12 @@ struct npc_time_rift : public NullCreatureAI
|
||||
events.ScheduleEvent(EVENT_CHECK_DEATH, 8000);
|
||||
}
|
||||
|
||||
void SetGUID(ObjectGuid guid, int32) override
|
||||
void JustSummoned(Creature* creature) override
|
||||
{
|
||||
_riftKeeperGUID = guid;
|
||||
if (creature->GetEntry() != NPC_AEONUS)
|
||||
{
|
||||
_riftKeeperGUID = creature->GetGUID();
|
||||
}
|
||||
}
|
||||
|
||||
void DoSummonAtRift(uint32 entry)
|
||||
@@ -284,16 +280,15 @@ struct npc_time_rift : public NullCreatureAI
|
||||
Position pos = me->GetNearPosition(10.0f, 2 * M_PI * rand_norm());
|
||||
|
||||
if (Creature* summon = me->SummonCreature(entry, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 150000))
|
||||
if (_instance)
|
||||
{
|
||||
if (Creature* medivh = _instance->GetCreature(DATA_MEDIVH))
|
||||
{
|
||||
if (Unit* medivh = ObjectAccessor::GetUnit(*me, _instance->GetGuidData(DATA_MEDIVH)))
|
||||
{
|
||||
float o = medivh->GetAngle(summon) + frand(-1.0f, 1.0f);
|
||||
summon->SetHomePosition(medivh->GetPositionX() + 14.0f * cos(o), medivh->GetPositionY() + 14.0f * std::sin(o), medivh->GetPositionZ(), summon->GetAngle(medivh));
|
||||
summon->GetMotionMaster()->MoveTargetedHome(true);
|
||||
summon->SetReactState(REACT_DEFENSIVE);
|
||||
}
|
||||
float o = medivh->GetAngle(summon) + frand(-1.0f, 1.0f);
|
||||
summon->SetHomePosition(medivh->GetPositionX() + 14.0f * cos(o), medivh->GetPositionY() + 14.0f * std::sin(o), medivh->GetPositionZ(), summon->GetAngle(medivh));
|
||||
summon->GetMotionMaster()->MoveTargetedHome(true);
|
||||
summon->SetReactState(REACT_DEFENSIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoSelectSummon()
|
||||
@@ -326,8 +321,6 @@ struct npc_time_rift : public NullCreatureAI
|
||||
Creature* riftKeeper = ObjectAccessor::GetCreature(*me, _riftKeeperGUID);
|
||||
if (!riftKeeper || !riftKeeper->IsAlive())
|
||||
{
|
||||
_instance->SetGuidData(DATA_RIFT_KILLED, me->GetGUID());
|
||||
|
||||
me->DespawnOrUnsummon(0);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -24,13 +24,15 @@
|
||||
|
||||
#define DataHeader "TBM"
|
||||
|
||||
uint32 const EncounterCount = 3;
|
||||
|
||||
#define TheBlackMorassScriptName "instance_the_black_morass"
|
||||
|
||||
enum DataTypes
|
||||
{
|
||||
TYPE_CHRONO_LORD_DEJA = 0,
|
||||
TYPE_TEMPORUS = 1,
|
||||
TYPE_AEONUS = 2,
|
||||
DATA_CHRONO_LORD_DEJA = 0,
|
||||
DATA_TEMPORUS = 1,
|
||||
DATA_AEONUS = 2,
|
||||
MAX_ENCOUNTER = 3,
|
||||
|
||||
DATA_MEDIVH = 10,
|
||||
@@ -89,16 +91,9 @@ enum Misc
|
||||
SPELL_RIFT_CHANNEL = 31387,
|
||||
SPELL_TELEPORT_VISUAL = 7791,
|
||||
|
||||
EVENT_NEXT_PORTAL = 1,
|
||||
EVENT_SUMMON_KEEPER_1 = 2,
|
||||
EVENT_SUMMON_KEEPER_2 = 3,
|
||||
EVENT_SUMMON_KEEPER_3 = 4,
|
||||
EVENT_SUMMON_KEEPER_4 = 5,
|
||||
EVENT_WIPE_1 = 6,
|
||||
EVENT_WIPE_2 = 7,
|
||||
EVENT_WIPE_3 = 8,
|
||||
ACTION_OUTRO = 1,
|
||||
|
||||
ACTION_OUTRO = 1
|
||||
CONTEXT_GROUP_RIFTS = 1
|
||||
};
|
||||
|
||||
enum medivhSays
|
||||
|
||||
Reference in New Issue
Block a user