mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-25 06:36:24 +00:00
Merge branch 'master' into Playerbot
This commit is contained in:
@@ -119,6 +119,47 @@ struct boss_malchezaar : public BossAI
|
||||
{
|
||||
Initialize();
|
||||
_Reset();
|
||||
|
||||
ScheduleHealthCheckEvent(60, [&] {
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
_phase = 2;
|
||||
DoCastSelf(SPELL_EQUIP_AXES);
|
||||
Talk(SAY_AXE_TOSS1);
|
||||
DoCastSelf(SPELL_THRASH_AURA, true);
|
||||
SetEquipmentSlots(false, EQUIP_ID_AXE, EQUIP_ID_AXE, EQUIP_NO_CHANGE);
|
||||
me->SetCanDualWield(true);
|
||||
me->SetAttackTime(OFF_ATTACK, (me->GetAttackTime(BASE_ATTACK) * 150) / 100);
|
||||
|
||||
scheduler.Schedule(5s, 10s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_SUNDER_ARMOR);
|
||||
context.Repeat();
|
||||
});
|
||||
|
||||
scheduler.CancelGroup(GROUP_SHADOW_WORD_PAIN);
|
||||
});
|
||||
|
||||
ScheduleHealthCheckEvent(30, [&] {
|
||||
me->RemoveAurasDueToSpell(SPELL_THRASH_AURA);
|
||||
Talk(SAY_AXE_TOSS2);
|
||||
_phase = PHASE_THREE;
|
||||
clearweapons();
|
||||
|
||||
me->SummonCreature(NPC_MALCHEZARS_AXE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000);
|
||||
|
||||
scheduler.Schedule(20s, 30s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_AMPLIFY_DAMAGE, 1);
|
||||
context.Repeat();
|
||||
}).Schedule(20s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_SHADOW_WORD_PAIN);
|
||||
context.SetGroup(GROUP_SHADOW_WORD_PAIN);
|
||||
context.Repeat();
|
||||
});
|
||||
|
||||
scheduler.CancelGroup(GROUP_ENFEEBLE);
|
||||
});
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
@@ -183,49 +224,6 @@ struct boss_malchezaar : public BossAI
|
||||
});
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (me->HealthBelowPctDamaged(60, damage) && _phase == PHASE_ONE)
|
||||
{
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
_phase = 2;
|
||||
DoCastSelf( SPELL_EQUIP_AXES);
|
||||
Talk(SAY_AXE_TOSS1);
|
||||
DoCastSelf( SPELL_THRASH_AURA, true);
|
||||
SetEquipmentSlots(false, EQUIP_ID_AXE, EQUIP_ID_AXE, EQUIP_NO_CHANGE);
|
||||
me->SetCanDualWield(true);
|
||||
me->SetAttackTime(OFF_ATTACK, (me->GetAttackTime(BASE_ATTACK) * 150) / 100);
|
||||
|
||||
scheduler.Schedule(5s, 10s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_SUNDER_ARMOR);
|
||||
context.Repeat();
|
||||
});
|
||||
|
||||
scheduler.CancelGroup(GROUP_SHADOW_WORD_PAIN);
|
||||
}
|
||||
else if (me->HealthBelowPctDamaged(30, damage) && _phase == PHASE_TWO)
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_THRASH_AURA);
|
||||
Talk(SAY_AXE_TOSS2);
|
||||
_phase = PHASE_THREE;
|
||||
clearweapons();
|
||||
|
||||
me->SummonCreature(NPC_MALCHEZARS_AXE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000);
|
||||
|
||||
scheduler.Schedule(20s, 30s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_AMPLIFY_DAMAGE, 1);
|
||||
context.Repeat();
|
||||
}).Schedule(20s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_SHADOW_WORD_PAIN);
|
||||
context.SetGroup(GROUP_SHADOW_WORD_PAIN);
|
||||
context.Repeat();
|
||||
});;
|
||||
}
|
||||
}
|
||||
|
||||
void EnfeebleHealthEffect()
|
||||
{
|
||||
std::list<Unit*> targetList;
|
||||
|
||||
@@ -56,7 +56,8 @@ public:
|
||||
_currentRift = 0;
|
||||
_shieldPercent = 100;
|
||||
_encounterNPCs.clear();
|
||||
_canSpawnPortal = true; // Delay after bosses
|
||||
_noBossSpawnDelay = true; // Delay after bosses
|
||||
_eventStatus = EVENT_PREPARE;
|
||||
}
|
||||
|
||||
void CleanupInstance()
|
||||
@@ -72,10 +73,24 @@ public:
|
||||
_availableRiftPositions.push_back(pos);
|
||||
}
|
||||
|
||||
// prevent getting stuck if event fails during boss break
|
||||
_noBossSpawnDelay = true;
|
||||
|
||||
instance->LoadGrid(-2023.0f, 7121.0f);
|
||||
if (Creature* medivh = GetCreature(DATA_MEDIVH))
|
||||
{
|
||||
medivh->DespawnOrUnsummon(0ms, 3s);
|
||||
medivh->Respawn();
|
||||
}
|
||||
for (ObjectGuid const& guid : _encounterNPCs)
|
||||
{
|
||||
if (guid.GetEntry() == NPC_DP_BEAM_STALKER)
|
||||
{
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
{
|
||||
creature->Respawn();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,8 +136,8 @@ public:
|
||||
case NPC_RIFT_LORD:
|
||||
case NPC_RIFT_LORD_2:
|
||||
case NPC_TIME_RIFT:
|
||||
case NPC_INFINITE_ASSASIN:
|
||||
case NPC_INFINITE_ASSASIN_2:
|
||||
case NPC_INFINITE_ASSASSIN:
|
||||
case NPC_INFINITE_ASSASSIN_2:
|
||||
case NPC_INFINITE_WHELP:
|
||||
case NPC_INFINITE_CHRONOMANCER:
|
||||
case NPC_INFINITE_CHRONOMANCER_2:
|
||||
@@ -143,14 +158,14 @@ public:
|
||||
case DATA_CHRONO_LORD_DEJA:
|
||||
case DATA_TEMPORUS:
|
||||
{
|
||||
_canSpawnPortal = false;
|
||||
_noBossSpawnDelay = false;
|
||||
|
||||
_scheduler.Schedule(2min + 30s, [this](TaskContext)
|
||||
{
|
||||
_canSpawnPortal = true;
|
||||
_noBossSpawnDelay = true;
|
||||
ScheduleNextPortal(0s, Position(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
});
|
||||
|
||||
ScheduleNextPortal(2min + 30s, Position(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -163,26 +178,27 @@ public:
|
||||
|
||||
void OnPlayerEnter(Player* player) override
|
||||
{
|
||||
if (instance->GetPlayersCountExceptGMs() <= 1 && GetBossState(DATA_AEONUS) != DONE)
|
||||
if (instance->GetPlayersCountExceptGMs() <= 1 && GetBossState(DATA_AEONUS) != DONE && _eventStatus != EVENT_IN_PROGRESS)
|
||||
{
|
||||
CleanupInstance();
|
||||
}
|
||||
|
||||
player->SendUpdateWorldState(WORLD_STATE_BM, _currentRift > 0 ? 1 : 0);
|
||||
player->SendUpdateWorldState(WORLD_STATE_BM, _eventStatus);
|
||||
player->SendUpdateWorldState(WORLD_STATE_BM_SHIELD, _shieldPercent);
|
||||
player->SendUpdateWorldState(WORLD_STATE_BM_RIFT, _currentRift);
|
||||
}
|
||||
|
||||
void ScheduleNextPortal(Milliseconds time, Position lastPosition)
|
||||
{
|
||||
// only one rift can be scheduled at any time
|
||||
_scheduler.CancelGroup(CONTEXT_GROUP_RIFTS);
|
||||
|
||||
_scheduler.Schedule(time, [this, lastPosition](TaskContext context)
|
||||
{
|
||||
if (GetCreature(DATA_MEDIVH))
|
||||
{
|
||||
// Spawning prevented - there's a 150s delay after a boss dies.
|
||||
if (!_canSpawnPortal)
|
||||
// Spawning prevented: after-boss-delay or event failed/not started or last portal spawned
|
||||
if (!_noBossSpawnDelay || _eventStatus == EVENT_PREPARE || _currentRift >= 18)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -208,19 +224,10 @@ public:
|
||||
|
||||
instance->SummonCreature(NPC_TIME_RIFT, spawnPos);
|
||||
|
||||
// Here we check if we have available rift spots.
|
||||
if (_currentRift < 18)
|
||||
{
|
||||
if (!_availableRiftPositions.empty())
|
||||
{
|
||||
context.Repeat((_currentRift >= 13 ? 2min : 90s));
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Repeat(4s);
|
||||
}
|
||||
}
|
||||
// queue next portal if group doesn't kill keepers fast enough
|
||||
context.Repeat((_currentRift >= 13 ? 2min : 90s));
|
||||
}
|
||||
// if no rift positions are available, the next rift will be scheduled in OnCreatureRemove
|
||||
}
|
||||
|
||||
context.SetGroup(CONTEXT_GROUP_RIFTS);
|
||||
@@ -241,8 +248,8 @@ public:
|
||||
case NPC_RIFT_KEEPER_MAGE:
|
||||
case NPC_RIFT_LORD:
|
||||
case NPC_RIFT_LORD_2:
|
||||
case NPC_INFINITE_ASSASIN:
|
||||
case NPC_INFINITE_ASSASIN_2:
|
||||
case NPC_INFINITE_ASSASSIN:
|
||||
case NPC_INFINITE_ASSASSIN_2:
|
||||
case NPC_INFINITE_WHELP:
|
||||
case NPC_INFINITE_CHRONOMANCER:
|
||||
case NPC_INFINITE_CHRONOMANCER_2:
|
||||
@@ -251,6 +258,7 @@ public:
|
||||
case NPC_INFINITE_VANQUISHER:
|
||||
case NPC_INFINITE_VANQUISHER_2:
|
||||
case NPC_DP_BEAM_STALKER:
|
||||
case NPC_DP_EMITTER_STALKER:
|
||||
_encounterNPCs.insert(creature->GetGUID());
|
||||
break;
|
||||
}
|
||||
@@ -263,7 +271,7 @@ public:
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_TIME_RIFT:
|
||||
if (_currentRift < 18)
|
||||
if (_currentRift < 18 && _noBossSpawnDelay && _eventStatus == EVENT_IN_PROGRESS)
|
||||
{
|
||||
if (_availableRiftPositions.size() < 3)
|
||||
{
|
||||
@@ -286,8 +294,8 @@ public:
|
||||
case NPC_RIFT_KEEPER_MAGE:
|
||||
case NPC_RIFT_LORD:
|
||||
case NPC_RIFT_LORD_2:
|
||||
case NPC_INFINITE_ASSASIN:
|
||||
case NPC_INFINITE_ASSASIN_2:
|
||||
case NPC_INFINITE_ASSASSIN:
|
||||
case NPC_INFINITE_ASSASSIN_2:
|
||||
case NPC_INFINITE_WHELP:
|
||||
case NPC_INFINITE_CHRONOMANCER:
|
||||
case NPC_INFINITE_CHRONOMANCER_2:
|
||||
@@ -295,6 +303,7 @@ public:
|
||||
case NPC_INFINITE_EXECUTIONER_2:
|
||||
case NPC_INFINITE_VANQUISHER:
|
||||
case NPC_INFINITE_VANQUISHER_2:
|
||||
case NPC_DP_EMITTER_STALKER:
|
||||
_encounterNPCs.erase(creature->GetGUID());
|
||||
break;
|
||||
}
|
||||
@@ -308,27 +317,14 @@ public:
|
||||
{
|
||||
case DATA_MEDIVH:
|
||||
{
|
||||
DoUpdateWorldState(WORLD_STATE_BM, 1);
|
||||
_eventStatus = EVENT_IN_PROGRESS;
|
||||
|
||||
DoUpdateWorldState(WORLD_STATE_BM, _eventStatus);
|
||||
DoUpdateWorldState(WORLD_STATE_BM_SHIELD, _shieldPercent);
|
||||
DoUpdateWorldState(WORLD_STATE_BM_RIFT, _currentRift);
|
||||
|
||||
ScheduleNextPortal(3s, Position(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
|
||||
for (ObjectGuid const& guid : _encounterNPCs)
|
||||
{
|
||||
if (guid.GetEntry() == NPC_DP_BEAM_STALKER)
|
||||
{
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
{
|
||||
if (!creature->IsAlive())
|
||||
{
|
||||
creature->Respawn(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case DATA_DAMAGE_SHIELD:
|
||||
@@ -348,6 +344,8 @@ public:
|
||||
|
||||
if (!_shieldPercent)
|
||||
{
|
||||
_eventStatus = EVENT_PREPARE;
|
||||
|
||||
if (Creature* medivh = GetCreature(DATA_MEDIVH))
|
||||
{
|
||||
if (medivh->IsAlive() && medivh->IsAIEnabled)
|
||||
@@ -404,6 +402,12 @@ public:
|
||||
GuidSet encounterNPCSCopy = _encounterNPCs;
|
||||
for (ObjectGuid const& guid : encounterNPCSCopy)
|
||||
{
|
||||
// Don't despawn permanent visual effect NPC twice or it won't respawn correctly
|
||||
if (guid.GetEntry() == NPC_DP_BEAM_STALKER)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
{
|
||||
creature->CastSpell(creature, SPELL_TELEPORT_VISUAL, true);
|
||||
@@ -412,6 +416,16 @@ public:
|
||||
}
|
||||
|
||||
_scheduler.CancelAll();
|
||||
|
||||
// Step 4 - Schedule instance cleanup without player interaction
|
||||
_scheduler.Schedule(300s, [this](TaskContext)
|
||||
{
|
||||
CleanupInstance();
|
||||
|
||||
DoUpdateWorldState(WORLD_STATE_BM, _eventStatus);
|
||||
DoUpdateWorldState(WORLD_STATE_BM_SHIELD, _shieldPercent);
|
||||
DoUpdateWorldState(WORLD_STATE_BM_RIFT, _currentRift);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -447,7 +461,8 @@ public:
|
||||
GuidSet _encounterNPCs;
|
||||
uint8 _currentRift;
|
||||
int8 _shieldPercent;
|
||||
bool _canSpawnPortal;
|
||||
bool _noBossSpawnDelay;
|
||||
EventStatus _eventStatus;
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -43,9 +43,9 @@ enum medivhMisc
|
||||
EVENT_OUTRO_8 = 17
|
||||
};
|
||||
|
||||
static std::vector<uint32> firstWave = { NPC_INFINITE_ASSASIN, NPC_INFINITE_WHELP, NPC_INFINITE_CHRONOMANCER };
|
||||
static std::vector<uint32> secondWave = { NPC_INFINITE_EXECUTIONER, NPC_INFINITE_CHRONOMANCER, NPC_INFINITE_WHELP, NPC_INFINITE_ASSASIN };
|
||||
static std::vector<uint32> thirdWave = { NPC_INFINITE_EXECUTIONER, NPC_INFINITE_VANQUISHER, NPC_INFINITE_CHRONOMANCER, NPC_INFINITE_ASSASIN };
|
||||
static std::vector<uint32> firstWave = { NPC_INFINITE_ASSASSIN, NPC_INFINITE_WHELP, NPC_INFINITE_CHRONOMANCER };
|
||||
static std::vector<uint32> secondWave = { NPC_INFINITE_EXECUTIONER, NPC_INFINITE_CHRONOMANCER, NPC_INFINITE_WHELP, NPC_INFINITE_ASSASSIN };
|
||||
static std::vector<uint32> thirdWave = { NPC_INFINITE_EXECUTIONER, NPC_INFINITE_VANQUISHER, NPC_INFINITE_CHRONOMANCER, NPC_INFINITE_ASSASSIN };
|
||||
|
||||
class NpcRunToHome : public BasicEvent
|
||||
{
|
||||
@@ -323,8 +323,8 @@ struct npc_time_rift : public NullCreatureAI
|
||||
{
|
||||
switch (entry)
|
||||
{
|
||||
case NPC_INFINITE_ASSASIN:
|
||||
entry = NPC_INFINITE_ASSASIN_2;
|
||||
case NPC_INFINITE_ASSASSIN:
|
||||
entry = NPC_INFINITE_ASSASSIN_2;
|
||||
break;
|
||||
case NPC_INFINITE_CHRONOMANCER:
|
||||
entry = NPC_INFINITE_CHRONOMANCER_2;
|
||||
|
||||
@@ -36,13 +36,10 @@ enum DataTypes
|
||||
MAX_ENCOUNTER = 3,
|
||||
|
||||
DATA_MEDIVH = 10,
|
||||
DATA_RIFT_KILLED = 11,
|
||||
|
||||
DATA_DAMAGE_SHIELD = 12,
|
||||
DATA_SHIELD_PERCENT = 13,
|
||||
DATA_RIFT_NUMBER = 14,
|
||||
|
||||
DATA_SUMMONED_NPC = 20,
|
||||
DATA_DELETED_NPC = 21
|
||||
DATA_RIFT_NUMBER = 14
|
||||
};
|
||||
|
||||
enum WorldStateIds
|
||||
@@ -52,6 +49,12 @@ enum WorldStateIds
|
||||
WORLD_STATE_BM_RIFT = 2784
|
||||
};
|
||||
|
||||
enum EventStatus
|
||||
{
|
||||
EVENT_PREPARE = 0,
|
||||
EVENT_IN_PROGRESS = 1
|
||||
};
|
||||
|
||||
enum QuestIds
|
||||
{
|
||||
QUEST_OPENING_PORTAL = 10297,
|
||||
@@ -75,13 +78,13 @@ enum CreatureIds
|
||||
NPC_INFINITE_TIMEREAVER = 21698,
|
||||
NPC_AEONUS = 17881,
|
||||
|
||||
NPC_INFINITE_ASSASIN = 17835,
|
||||
NPC_INFINITE_ASSASSIN = 17835,
|
||||
NPC_INFINITE_WHELP = 21818,
|
||||
NPC_INFINITE_CHRONOMANCER = 17892,
|
||||
NPC_INFINITE_EXECUTIONER = 18994,
|
||||
NPC_INFINITE_VANQUISHER = 18995,
|
||||
|
||||
NPC_INFINITE_ASSASIN_2 = 21137,
|
||||
NPC_INFINITE_ASSASSIN_2 = 21137,
|
||||
NPC_INFINITE_CHRONOMANCER_2 = 21136,
|
||||
NPC_INFINITE_EXECUTIONER_2 = 21138,
|
||||
NPC_INFINITE_VANQUISHER_2 = 21139,
|
||||
|
||||
@@ -44,6 +44,7 @@ enum blySays
|
||||
|
||||
enum blySpells
|
||||
{
|
||||
SPELL_BLYS_BAND_ESCAPE = 11365,
|
||||
SPELL_SHIELD_BASH = 11972,
|
||||
SPELL_REVENGE = 12170
|
||||
};
|
||||
@@ -64,6 +65,7 @@ public:
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
ableToPortHome = false;
|
||||
startedFight = false;
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
postGossipStep = 0;
|
||||
@@ -74,16 +76,33 @@ public:
|
||||
InstanceScript* instance;
|
||||
|
||||
bool startedFight;
|
||||
bool ableToPortHome;
|
||||
uint32 postGossipStep;
|
||||
uint32 Text_Timer;
|
||||
uint32 ShieldBash_Timer;
|
||||
uint32 Revenge_Timer; //this is wrong, spell should never be used unless me->GetVictim() dodge, parry or block attack. Trinity support required.
|
||||
uint32 Revenge_Timer; //this is wrong, spell should never be used unless me->GetVictim() dodge, parry or block attack. Trinity support required.
|
||||
uint32 Porthome_Timer;
|
||||
ObjectGuid PlayerGUID;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
ShieldBash_Timer = 5000;
|
||||
Revenge_Timer = 8000;
|
||||
Porthome_Timer = 156000;
|
||||
ableToPortHome = false;
|
||||
startedFight = false;
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*reason*/) override
|
||||
{
|
||||
if (ableToPortHome)
|
||||
return;
|
||||
|
||||
if (instance->GetData(DATA_PYRAMID) == PYRAMID_KILLED_ALL_TROLLS)
|
||||
{
|
||||
ableToPortHome = true;
|
||||
Porthome_Timer = 156000;
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 /*id*/) override
|
||||
@@ -112,6 +131,7 @@ public:
|
||||
switch (postGossipStep)
|
||||
{
|
||||
case 1:
|
||||
startedFight = true;
|
||||
//weegli doesn't fight - he goes & blows up the door
|
||||
if (Creature* pWeegli = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_WEEGLI)))
|
||||
{
|
||||
@@ -128,6 +148,7 @@ public:
|
||||
me->SetFaction(FACTION_MONSTER);
|
||||
Player* target = ObjectAccessor::GetPlayer(*me, PlayerGUID);
|
||||
|
||||
switchFactionIfAlive(NPC_WEEGLI, target);
|
||||
switchFactionIfAlive(NPC_RAVEN, target);
|
||||
switchFactionIfAlive(NPC_ORO, target);
|
||||
switchFactionIfAlive(NPC_MURTA, target);
|
||||
@@ -146,6 +167,37 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if (Porthome_Timer <= diff && ableToPortHome == true)
|
||||
{
|
||||
if (Creature* weegli = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_WEEGLI)))
|
||||
{
|
||||
weegli->CastSpell(weegli, SPELL_BLYS_BAND_ESCAPE);
|
||||
weegli->DespawnOrUnsummon(10000);
|
||||
}
|
||||
if (Creature* raven = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_RAVEN)))
|
||||
{
|
||||
raven->CastSpell(raven, SPELL_BLYS_BAND_ESCAPE);
|
||||
raven->DespawnOrUnsummon(10000);
|
||||
}
|
||||
if (Creature* oro = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_ORO)))
|
||||
{
|
||||
oro->CastSpell(oro, SPELL_BLYS_BAND_ESCAPE);
|
||||
oro->DespawnOrUnsummon(10000);
|
||||
}
|
||||
if (Creature* murta = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_MURTA)))
|
||||
{
|
||||
murta->CastSpell(murta, SPELL_BLYS_BAND_ESCAPE);
|
||||
murta->DespawnOrUnsummon(10000);
|
||||
}
|
||||
DoCastSelf(SPELL_BLYS_BAND_ESCAPE);
|
||||
me->DespawnOrUnsummon(10000);
|
||||
Porthome_Timer = 156000; //set timer back so that the event doesn't keep triggering
|
||||
}
|
||||
else
|
||||
{
|
||||
Porthome_Timer -= diff;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
@@ -176,6 +228,7 @@ public:
|
||||
|
||||
void DoAction(int32 /*param*/) override
|
||||
{
|
||||
ableToPortHome = false;
|
||||
postGossipStep = 1;
|
||||
Text_Timer = 0;
|
||||
}
|
||||
@@ -211,9 +264,8 @@ public:
|
||||
|
||||
void sGossipHello(Player* player) override
|
||||
{
|
||||
if (instance->GetData(DATA_PYRAMID) >= PYRAMID_DESTROY_GATES && !startedFight)
|
||||
if (instance->GetData(DATA_PYRAMID) >= PYRAMID_MOVED_DOWNSTAIRS && !startedFight)
|
||||
{
|
||||
startedFight = true;
|
||||
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_BLY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
SendGossipMenuFor(player, 1517, me->GetGUID());
|
||||
}
|
||||
@@ -261,6 +313,17 @@ public:
|
||||
|
||||
instance->SetData(DATA_PYRAMID, PYRAMID_CAGES_OPEN);
|
||||
|
||||
//setting gossip option as soon as the cages open
|
||||
if(Creature* bly = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_BLY)))
|
||||
{
|
||||
bly->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
}
|
||||
|
||||
if(Creature* weegli = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_WEEGLI)))
|
||||
{
|
||||
weegli->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
}
|
||||
|
||||
//set bly & co to aggressive & start moving to top of stairs
|
||||
initBlyCrewMember(NPC_BLY, 1884.99f, 1263, 41.52f);
|
||||
initBlyCrewMember(NPC_RAVEN, 1882.5f, 1263, 41.52f);
|
||||
@@ -281,15 +344,6 @@ public:
|
||||
crew->GetMotionMaster()->MovePoint(1, { x, y, z, 4.78f });
|
||||
crew->SetFaction(FACTION_ESCORT_N_NEUTRAL_ACTIVE);
|
||||
|
||||
switch (entry)
|
||||
{
|
||||
case NPC_BLY:
|
||||
case NPC_WEEGLI:
|
||||
crew->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -429,13 +483,13 @@ public:
|
||||
{
|
||||
if (instance->GetData(DATA_PYRAMID) == PYRAMID_CAGES_OPEN)
|
||||
{
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
instance->SetData(DATA_PYRAMID, PYRAMID_ARRIVED_AT_STAIR);
|
||||
Talk(SAY_WEEGLI_OHNO);
|
||||
}
|
||||
else if (instance->GetData(DATA_PYRAMID) == PYRAMID_KILLED_ALL_TROLLS)
|
||||
else if (instance->GetData(DATA_PYRAMID) >= PYRAMID_KILLED_ALL_TROLLS && instance->GetData(DATA_PYRAMID) < PYRAMID_DESTROY_GATES)
|
||||
{
|
||||
instance->SetData(DATA_PYRAMID, PYRAMID_MOVED_DOWNSTAIRS);
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
}
|
||||
else if (instance->GetData(DATA_PYRAMID) == PYRAMID_DESTROY_GATES)
|
||||
{
|
||||
@@ -452,13 +506,13 @@ public:
|
||||
|
||||
if (instance->GetData(DATA_PYRAMID) == PYRAMID_CAGES_OPEN)
|
||||
{
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
instance->SetData(DATA_PYRAMID, PYRAMID_ARRIVED_AT_STAIR);
|
||||
Talk(SAY_WEEGLI_OHNO);
|
||||
}
|
||||
else if (instance->GetData(DATA_PYRAMID) == PYRAMID_KILLED_ALL_TROLLS)
|
||||
else if (instance->GetData(DATA_PYRAMID) >= PYRAMID_KILLED_ALL_TROLLS && instance->GetData(DATA_PYRAMID) < PYRAMID_DESTROY_GATES)
|
||||
{
|
||||
instance->SetData(DATA_PYRAMID, PYRAMID_MOVED_DOWNSTAIRS);
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
}
|
||||
else if (instance->GetData(DATA_PYRAMID) == PYRAMID_DESTROY_GATES)
|
||||
{
|
||||
@@ -476,10 +530,6 @@ public:
|
||||
me->SetHomePosition(1858.57f, 1146.35f, 14.745f, 3.85f);
|
||||
Talk(SAY_WEEGLI_OK_I_GO);
|
||||
instance->SetData(DATA_PYRAMID, PYRAMID_DESTROY_GATES);
|
||||
if (Creature* sergeantBly = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_BLY)))
|
||||
{
|
||||
sergeantBly->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,6 +551,7 @@ public:
|
||||
switch (instance->GetData(DATA_PYRAMID))
|
||||
{
|
||||
case PYRAMID_MOVED_DOWNSTAIRS:
|
||||
case PYRAMID_KILLED_ALL_TROLLS:
|
||||
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_WEEGLI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
SendGossipMenuFor(player, 1514, me->GetGUID()); //if event can proceed to end
|
||||
break;
|
||||
@@ -508,7 +559,7 @@ public:
|
||||
SendGossipMenuFor(player, 1511, me->GetGUID()); //if event not started
|
||||
break;
|
||||
default:
|
||||
SendGossipMenuFor(player, 1513, me->GetGUID()); //if event are in progress
|
||||
SendGossipMenuFor(player, 1513, me->GetGUID()); //if event is in progress
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -58,17 +58,6 @@ enum Spells
|
||||
SPELL_STONED = 33652,
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_GROWTH = 1,
|
||||
EVENT_CAVE_IN = 2,
|
||||
EVENT_GROUND_SLAM = 3,
|
||||
EVENT_HURTFUL_STRIKE = 4,
|
||||
EVENT_REVERBERATION = 5,
|
||||
EVENT_SHATTER = 6,
|
||||
EVENT_RECENTLY_SPOKEN = 7
|
||||
};
|
||||
|
||||
struct boss_gruul : public BossAI
|
||||
{
|
||||
boss_gruul(Creature* creature) : BossAI(creature, DATA_GRUUL) { }
|
||||
@@ -76,7 +65,8 @@ struct boss_gruul : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
_caveInTimer = 29000;
|
||||
_recentlySpoken = false;
|
||||
_caveInTimer = 29000ms;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
@@ -84,20 +74,61 @@ struct boss_gruul : public BossAI
|
||||
_JustEngagedWith();
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
events.ScheduleEvent(EVENT_GROWTH, 30000);
|
||||
events.ScheduleEvent(EVENT_CAVE_IN, _caveInTimer);
|
||||
events.ScheduleEvent(EVENT_REVERBERATION, 20000);
|
||||
events.ScheduleEvent(EVENT_HURTFUL_STRIKE, 10000);
|
||||
events.ScheduleEvent(EVENT_GROUND_SLAM, 35000);
|
||||
scheduler.Schedule(30300ms, [this](TaskContext context)
|
||||
{
|
||||
Talk(EMOTE_GROW);
|
||||
DoCastSelf(SPELL_GROWTH);
|
||||
context.Repeat(30300ms);
|
||||
}).Schedule(_caveInTimer, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_CAVE_IN);
|
||||
if (_caveInTimer > 4000ms)
|
||||
{
|
||||
_caveInTimer = _caveInTimer - 1500ms;
|
||||
}
|
||||
context.Repeat(_caveInTimer);
|
||||
}).Schedule(20s, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_REVERBERATION);
|
||||
context.Repeat(22s);
|
||||
}).Schedule(10s, [this](TaskContext context)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 5.0f))
|
||||
{
|
||||
DoCast(target, SPELL_HURTFUL_STRIKE);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCastVictim(SPELL_HURTFUL_STRIKE);
|
||||
}
|
||||
context.Repeat(15s);
|
||||
}).Schedule(35s, [this](TaskContext context)
|
||||
{
|
||||
Talk(SAY_SLAM);
|
||||
DoCastSelf(SPELL_GROUND_SLAM);
|
||||
scheduler.DelayAll(9701ms);
|
||||
scheduler.Schedule(9700ms, [this](TaskContext)
|
||||
{
|
||||
Talk(SAY_SHATTER);
|
||||
me->RemoveAurasDueToSpell(SPELL_LOOK_AROUND);
|
||||
DoCastSelf(SPELL_SHATTER);
|
||||
});
|
||||
context.Repeat(60s);
|
||||
});
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*who*/) override
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_RECENTLY_SPOKEN) == 0)
|
||||
if (!_recentlySpoken)
|
||||
{
|
||||
events.ScheduleEvent(EVENT_RECENTLY_SPOKEN, 5000);
|
||||
Talk(SAY_SLAY);
|
||||
_recentlySpoken = true;
|
||||
}
|
||||
|
||||
scheduler.Schedule(5s, [this](TaskContext)
|
||||
{
|
||||
_recentlySpoken = false;
|
||||
});
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -111,52 +142,7 @@ struct boss_gruul : public BossAI
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_GROWTH:
|
||||
Talk(EMOTE_GROW);
|
||||
DoCast(me, SPELL_GROWTH);
|
||||
events.ScheduleEvent(EVENT_GROWTH, 30000);
|
||||
break;
|
||||
case EVENT_CAVE_IN:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
me->CastSpell(target, SPELL_CAVE_IN, false);
|
||||
if (_caveInTimer >= 4000)
|
||||
_caveInTimer -= 1500;
|
||||
events.ScheduleEvent(EVENT_CAVE_IN, _caveInTimer);
|
||||
break;
|
||||
case EVENT_REVERBERATION:
|
||||
me->CastSpell(me, SPELL_REVERBERATION, false);
|
||||
events.ScheduleEvent(EVENT_REVERBERATION, 22000);
|
||||
break;
|
||||
case EVENT_HURTFUL_STRIKE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 5.0f))
|
||||
{
|
||||
me->CastSpell(target, SPELL_HURTFUL_STRIKE, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->CastSpell(me->GetVictim(), SPELL_HURTFUL_STRIKE, false);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_HURTFUL_STRIKE, 15000);
|
||||
break;
|
||||
case EVENT_GROUND_SLAM:
|
||||
Talk(SAY_SLAM);
|
||||
me->CastSpell(me, SPELL_GROUND_SLAM, false);
|
||||
events.DelayEvents(8001);
|
||||
events.ScheduleEvent(EVENT_GROUND_SLAM, 60000);
|
||||
events.ScheduleEvent(EVENT_SHATTER, 8000);
|
||||
break;
|
||||
case EVENT_SHATTER:
|
||||
Talk(SAY_SHATTER);
|
||||
me->RemoveAurasDueToSpell(SPELL_LOOK_AROUND);
|
||||
me->CastSpell(me, SPELL_SHATTER, false);
|
||||
break;
|
||||
}
|
||||
scheduler.Update(diff);
|
||||
|
||||
if (!me->HasUnitState(UNIT_STATE_ROOT))
|
||||
{
|
||||
@@ -165,7 +151,8 @@ struct boss_gruul : public BossAI
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 _caveInTimer;
|
||||
std::chrono::milliseconds _caveInTimer;
|
||||
bool _recentlySpoken;
|
||||
};
|
||||
|
||||
struct npc_invisible_tractor_beam_source : public NullCreatureAI
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "gruuls_lair.h"
|
||||
|
||||
enum HighKingMaulgar
|
||||
@@ -59,39 +60,49 @@ enum HighKingMaulgar
|
||||
ACTION_ADD_DEATH = 1
|
||||
};
|
||||
|
||||
enum HKMEvents
|
||||
{
|
||||
EVENT_RECENTLY_SPOKEN = 1,
|
||||
EVENT_ARCING_SMASH = 2,
|
||||
EVENT_MIGHTY_BLOW = 3,
|
||||
EVENT_WHIRLWIND = 4,
|
||||
EVENT_CHARGING = 5,
|
||||
EVENT_ROAR = 6,
|
||||
EVENT_CHECK_HEALTH = 7,
|
||||
|
||||
EVENT_ADD_ABILITY1 = 10,
|
||||
EVENT_ADD_ABILITY2 = 11,
|
||||
EVENT_ADD_ABILITY3 = 12,
|
||||
EVENT_ADD_ABILITY4 = 13
|
||||
};
|
||||
|
||||
struct boss_high_king_maulgar : public BossAI
|
||||
{
|
||||
boss_high_king_maulgar(Creature* creature) : BossAI(creature, DATA_MAULGAR) { }
|
||||
boss_high_king_maulgar(Creature* creature) : BossAI(creature, DATA_MAULGAR)
|
||||
{
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
_recentlySpoken = false;
|
||||
me->SetLootMode(0);
|
||||
ScheduleHealthCheckEvent(50, [&]{
|
||||
Talk(SAY_ENRAGE);
|
||||
DoCastSelf(SPELL_FLURRY);
|
||||
|
||||
scheduler.Schedule(0ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_BERSERKER_C);
|
||||
context.Repeat(35s);
|
||||
}).Schedule(0ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_ROAR);
|
||||
context.Repeat(20600ms, 29100ms);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_RECENTLY_SPOKEN) == 0)
|
||||
if(!_recentlySpoken)
|
||||
{
|
||||
events.ScheduleEvent(EVENT_RECENTLY_SPOKEN, 5s);
|
||||
Talk(SAY_SLAY);
|
||||
_recentlySpoken = true;
|
||||
}
|
||||
|
||||
scheduler.Schedule(5s, [this](TaskContext)
|
||||
{
|
||||
_recentlySpoken = false;
|
||||
});
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -126,10 +137,20 @@ struct boss_high_king_maulgar : public BossAI
|
||||
_JustEngagedWith();
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
events.ScheduleEvent(EVENT_ARCING_SMASH, 10s);
|
||||
events.ScheduleEvent(EVENT_MIGHTY_BLOW, 15s);
|
||||
events.ScheduleEvent(EVENT_WHIRLWIND, 54s);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 500ms);
|
||||
scheduler.Schedule(9500ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_ARCING_SMASH);
|
||||
context.Repeat(9500ms, 12s);
|
||||
}).Schedule(15700ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_MIGHTY_BLOW);
|
||||
context.Repeat(16200ms, 19s);
|
||||
}).Schedule(67000ms, [this](TaskContext context)
|
||||
{
|
||||
scheduler.DelayAll(15s);
|
||||
DoCastSelf(SPELL_WHIRLWIND);
|
||||
context.Repeat(45s, 60s);
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
@@ -137,49 +158,12 @@ struct boss_high_king_maulgar : public BossAI
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_ARCING_SMASH:
|
||||
me->CastSpell(me->GetVictim(), SPELL_ARCING_SMASH, false);
|
||||
events.ScheduleEvent(EVENT_ARCING_SMASH, 10s);
|
||||
break;
|
||||
case EVENT_MIGHTY_BLOW:
|
||||
me->CastSpell(me->GetVictim(), SPELL_MIGHTY_BLOW, false);
|
||||
events.ScheduleEvent(EVENT_MIGHTY_BLOW, 15s);
|
||||
break;
|
||||
case EVENT_WHIRLWIND:
|
||||
events.DelayEvents(15s);
|
||||
me->CastSpell(me, SPELL_WHIRLWIND, false);
|
||||
events.ScheduleEvent(EVENT_WHIRLWIND, 54s);
|
||||
break;
|
||||
case EVENT_CHECK_HEALTH:
|
||||
if (me->HealthBelowPct(50))
|
||||
{
|
||||
Talk(SAY_ENRAGE);
|
||||
me->CastSpell(me, SPELL_FLURRY, true);
|
||||
events.ScheduleEvent(EVENT_CHARGING, 0s);
|
||||
events.ScheduleEvent(EVENT_ROAR, 30s);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 500ms);
|
||||
break;
|
||||
case EVENT_ROAR:
|
||||
me->CastSpell(me, SPELL_ROAR, false);
|
||||
events.ScheduleEvent(EVENT_ROAR, 40s);
|
||||
break;
|
||||
case EVENT_CHARGING:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1))
|
||||
me->CastSpell(target, SPELL_BERSERKER_C, false);
|
||||
events.ScheduleEvent(EVENT_CHARGING, 35s);
|
||||
break;
|
||||
}
|
||||
scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
bool _recentlySpoken;
|
||||
};
|
||||
|
||||
struct boss_olm_the_summoner : public ScriptedAI
|
||||
@@ -187,15 +171,18 @@ struct boss_olm_the_summoner : public ScriptedAI
|
||||
boss_olm_the_summoner(Creature* creature) : ScriptedAI(creature), summons(me)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
_scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
EventMap events;
|
||||
SummonList summons;
|
||||
InstanceScript* instance;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
_scheduler.CancelAll();
|
||||
summons.DespawnAll();
|
||||
instance->SetBossState(DATA_MAULGAR, NOT_STARTED);
|
||||
}
|
||||
@@ -214,9 +201,22 @@ struct boss_olm_the_summoner : public ScriptedAI
|
||||
me->SetInCombatWithZone();
|
||||
instance->SetBossState(DATA_MAULGAR, IN_PROGRESS);
|
||||
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 500ms);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 5s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 6500ms);
|
||||
_scheduler.Schedule(1200ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_SUMMON_WFH);
|
||||
context.Repeat(48500ms);
|
||||
}).Schedule(6050ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_DARK_DECAY);
|
||||
context.Repeat(6050ms);
|
||||
}).Schedule(6500ms, [this](TaskContext context)
|
||||
{
|
||||
if (me->HealthBelowPct(90))
|
||||
{
|
||||
DoCastRandomTarget(SPELL_DEATH_COIL);
|
||||
}
|
||||
context.Repeat(6s, 13500ms);
|
||||
});
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -234,27 +234,12 @@ struct boss_olm_the_summoner : public ScriptedAI
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
_scheduler.Update(diff);
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_ADD_ABILITY1:
|
||||
me->CastSpell(me, SPELL_SUMMON_WFH, false);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 50s);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY2:
|
||||
DoCastVictim(SPELL_DARK_DECAY);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 6500ms);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY3:
|
||||
DoCastRandomTarget(SPELL_DEATH_COIL);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 7s);
|
||||
break;
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
struct boss_kiggler_the_crazed : public ScriptedAI
|
||||
@@ -262,14 +247,17 @@ struct boss_kiggler_the_crazed : public ScriptedAI
|
||||
boss_kiggler_the_crazed(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
_scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
EventMap events;
|
||||
InstanceScript* instance;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
_scheduler.CancelAll();
|
||||
instance->SetBossState(DATA_MAULGAR, NOT_STARTED);
|
||||
}
|
||||
|
||||
@@ -278,10 +266,35 @@ struct boss_kiggler_the_crazed : public ScriptedAI
|
||||
me->SetInCombatWithZone();
|
||||
instance->SetBossState(DATA_MAULGAR, IN_PROGRESS);
|
||||
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 1500ms);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 5s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 25s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY4, 30s);
|
||||
_scheduler.Schedule(1200ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_LIGHTNING_BOLT);
|
||||
context.Repeat(2400ms);
|
||||
}).Schedule(29s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_ARCANE_SHOCK);
|
||||
context.Repeat(7200ms, 20600ms);
|
||||
}).Schedule(23s, [this](TaskContext context)
|
||||
{
|
||||
//changed to work similarly to Ikiss poly
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_GREATER_POLYMORPH);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, [&]
|
||||
(Unit* target) -> bool
|
||||
{
|
||||
return target && !target->IsImmunedToSpell(spellInfo);
|
||||
}))
|
||||
{
|
||||
DoCast(target, SPELL_GREATER_POLYMORPH);
|
||||
}
|
||||
context.Repeat(10900ms);
|
||||
}).Schedule(30s, [this](TaskContext context)
|
||||
{
|
||||
if (me->SelectNearestPlayer(30.0f))
|
||||
{
|
||||
DoCastAOE(SPELL_ARCANE_EXPLOSION);
|
||||
}
|
||||
context.Repeat(30s);
|
||||
});
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -294,36 +307,12 @@ struct boss_kiggler_the_crazed : public ScriptedAI
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_ADD_ABILITY1:
|
||||
DoCastVictim(SPELL_LIGHTNING_BOLT);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 1500ms);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY2:
|
||||
DoCastVictim(SPELL_ARCANE_SHOCK);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 5s);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY3:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1)) //target method should perhaps change
|
||||
me->CastSpell(target, SPELL_GREATER_POLYMORPH, false);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 11s);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY4:
|
||||
if (me->SelectNearestPlayer(30.0f))
|
||||
{
|
||||
DoCastAOE(SPELL_ARCANE_EXPLOSION);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY4, 30s);
|
||||
break;
|
||||
}
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
struct boss_blindeye_the_seer : public ScriptedAI
|
||||
@@ -331,14 +320,17 @@ struct boss_blindeye_the_seer : public ScriptedAI
|
||||
boss_blindeye_the_seer(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
_scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
EventMap events;
|
||||
InstanceScript* instance;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
_scheduler.CancelAll();
|
||||
instance->SetBossState(DATA_MAULGAR, NOT_STARTED);
|
||||
}
|
||||
|
||||
@@ -347,9 +339,22 @@ struct boss_blindeye_the_seer : public ScriptedAI
|
||||
me->SetInCombatWithZone();
|
||||
instance->SetBossState(DATA_MAULGAR, IN_PROGRESS);
|
||||
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 11s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 30s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 31s);
|
||||
_scheduler.Schedule(7200ms, [this](TaskContext context)
|
||||
{
|
||||
if (Unit* target = DoSelectLowestHpFriendly(60.0f, 50000))
|
||||
{
|
||||
DoCast(target, SPELL_HEAL);
|
||||
}
|
||||
context.Repeat(7200ms);
|
||||
}).Schedule(37500s, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_GREATER_PW_SHIELD);
|
||||
_scheduler.Schedule(1200ms, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_PRAYER_OH);
|
||||
});
|
||||
context.Repeat(54500ms, 63s);
|
||||
});
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -362,31 +367,12 @@ struct boss_blindeye_the_seer : public ScriptedAI
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_ADD_ABILITY1:
|
||||
if (Unit* target = DoSelectLowestHpFriendly(60.0f, 50000))
|
||||
{
|
||||
DoCast(target, SPELL_HEAL);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 6s);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY2:
|
||||
DoCastSelf(SPELL_GREATER_PW_SHIELD);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 30s);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY3:
|
||||
me->CastSpell(me, SPELL_PRAYER_OH, false);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 30s);
|
||||
break;
|
||||
}
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
struct boss_krosh_firehand : public ScriptedAI
|
||||
@@ -394,14 +380,17 @@ struct boss_krosh_firehand : public ScriptedAI
|
||||
boss_krosh_firehand(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
_scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
EventMap events;
|
||||
InstanceScript* instance;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
_scheduler.CancelAll();
|
||||
instance->SetBossState(DATA_MAULGAR, NOT_STARTED);
|
||||
}
|
||||
|
||||
@@ -419,9 +408,22 @@ struct boss_krosh_firehand : public ScriptedAI
|
||||
me->SetInCombatWithZone();
|
||||
instance->SetBossState(DATA_MAULGAR, IN_PROGRESS);
|
||||
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 1500ms); //spellshield
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 3500ms); //greater fireball
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 8s); //blast wave (needs to check for players in range)
|
||||
_scheduler.Schedule(1200ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_SPELLSHIELD);
|
||||
context.Repeat(30300ms);
|
||||
}).Schedule(3600ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_GREATER_FIREBALL);
|
||||
context.Repeat(3600ms);
|
||||
}).Schedule(7200ms, [this](TaskContext context)
|
||||
{
|
||||
if (me->SelectNearestPlayer(15.0f))
|
||||
{
|
||||
DoCastAOE(SPELL_BLAST_WAVE);
|
||||
}
|
||||
context.Repeat(7200ms);
|
||||
});
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -434,31 +436,12 @@ struct boss_krosh_firehand : public ScriptedAI
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_ADD_ABILITY1:
|
||||
DoCastSelf(SPELL_SPELLSHIELD);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 30s);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY2:
|
||||
DoCastVictim(SPELL_GREATER_FIREBALL);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 1s);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY3:
|
||||
if (me->SelectNearestPlayer(15.0f))
|
||||
{
|
||||
DoCastAOE(SPELL_BLAST_WAVE);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 8s);
|
||||
break;
|
||||
}
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
void AddSC_boss_high_king_maulgar()
|
||||
|
||||
@@ -144,7 +144,28 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class spell_gargolmar_retalliation : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_gargolmar_retalliation);
|
||||
|
||||
bool CheckProc(ProcEventInfo& eventInfo)
|
||||
{
|
||||
if (!eventInfo.GetActor() || !eventInfo.GetProcTarget())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return GetTarget()->isInFront(eventInfo.GetActor(), M_PI);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckProc += AuraCheckProcFn(spell_gargolmar_retalliation::CheckProc);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_watchkeeper_gargolmar()
|
||||
{
|
||||
RegisterHellfireRampartsCreatureAI(boss_watchkeeper_gargolmar);
|
||||
RegisterSpellScript(spell_gargolmar_retalliation);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user