blackrock hold boss

This commit is contained in:
luis
2026-09-24 11:49:15 -03:00
parent fdb2c9392a
commit f4ee5e5bbc
9 changed files with 1831 additions and 2 deletions
+2
View File
@@ -222,6 +222,8 @@ class TC_GAME_API CreatureAI : public UnitAI
virtual void WaypointStarted(uint32 /*nodeId*/, uint32 /*pathId*/) { } virtual void WaypointStarted(uint32 /*nodeId*/, uint32 /*pathId*/) { }
virtual void WaypointReached(uint32 /*nodeId*/, uint32 /*pathId*/) { } virtual void WaypointReached(uint32 /*nodeId*/, uint32 /*pathId*/) { }
virtual void WaypointPathEnded(uint32 /*nodeId*/, uint32 /*pathId*/) { } virtual void WaypointPathEnded(uint32 /*nodeId*/, uint32 /*pathId*/) { }
// Called when the Creature reach spline end
virtual void OnSplineEndReached() {} // < DekkCore
/// == Fields ======================================= /// == Fields =======================================
+5
View File
@@ -647,6 +647,11 @@ void Unit::UpdateSplineMovement(uint32 t_diff)
if (Optional<AnimTier> animTier = movespline->GetAnimation()) if (Optional<AnimTier> animTier = movespline->GetAnimation())
SetAnimTier(*animTier); SetAnimTier(*animTier);
if (IsCreature() && IsAIEnabled())
{
ToCreature()->AI()->OnSplineEndReached();
}
} }
UpdateSplinePosition(); UpdateSplinePosition();
+1 -1
View File
@@ -1678,7 +1678,7 @@ void WorldSession::HandleSetStopConversation(WorldPackets::Misc::SetStopConversa
conversation->Remove(); conversation->Remove();
} }
void WorldSession::HandleFetchBleepProxies(WorldPackets::Misc::FetchBleepProxies& fetchBleepProxies) void WorldSession::HandleFetchBleepProxies(WorldPackets::Misc::FetchBleepProxies& /*fetchBleepProxies*/)
{ {
SendPacket(WorldPackets::Misc::FetchBleepProxiesResponse().Write()); SendPacket(WorldPackets::Misc::FetchBleepProxiesResponse().Write());
} }
@@ -0,0 +1,53 @@
/*
* Copyright (C) WowCommunity Project
*
* This SourceCode is NOT free a software. Please hold everything Private
* and read our Terms
*/
#include "AreaTrigger.h"
#include "AreaTriggerAI.h"
#include "ScriptMgr.h"
#include "black_rook_hold.h"
enum Spells
{
SPELL_BOULDER_EXPLOSION = 222388,
SPELL_BOULDER_DAMAGE = 222397,
SPELL_BOULDER_STUN = 222417,
};
// 100485
struct npc_brh_boulder_instance_trash : public ScriptedAI
{
npc_brh_boulder_instance_trash(Creature* creature) : ScriptedAI(creature) { }
// The instance will spawn it at top of stairs & make it move by spline
void OnSplineEndReached() override
{
me->CastSpell(me, SPELL_BOULDER_EXPLOSION, false);
me->DespawnOrUnsummon();
}
};
// 12428
struct at_brh_boulder : AreaTriggerAI
{
at_brh_boulder(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
void OnUnitEnter(Unit* unit) override
{
if (unit->IsPlayer() && !unit->HasAura(SPELL_BOULDER_STUN))
{
unit->CastSpell(unit, SPELL_BOULDER_DAMAGE, true);
unit->CastSpell(unit, SPELL_BOULDER_STUN, true);
}
}
};
void AddSC_black_rook_hold()
{
RegisterCreatureAI(npc_brh_boulder_instance_trash);
RegisterAreaTriggerAI(at_brh_boulder);
}
@@ -32,7 +32,8 @@ enum BRHDataTypes : uint8
DATA_ILLYSANNA_RAVENCREST, DATA_ILLYSANNA_RAVENCREST,
DATA_SMASHPITE_THE_HATEFUL, DATA_SMASHPITE_THE_HATEFUL,
DATA_LORD_KURTALOS_RAVENCREST, DATA_LORD_KURTALOS_RAVENCREST,
DATA_LORD_KURTALOS_RAVENCREST_STATE,
DATA_KURTALOS_STATE,
DATA_BOSS_1_POST_BOSS_DOOR DATA_BOSS_1_POST_BOSS_DOOR
}; };
@@ -42,6 +43,23 @@ enum BRHCreatureIds
BOSS_AMALGAM_OF_SOULS = 98542, BOSS_AMALGAM_OF_SOULS = 98542,
BOSS_ILLYSANNA_RAVENCREST = 98696, BOSS_ILLYSANNA_RAVENCREST = 98696,
BOSS_SMASHPITE_THE_HATEFUL = 98949, BOSS_SMASHPITE_THE_HATEFUL = 98949,
NPC_COMMANDER_SHEMDAHSOHN = 98706,
NPC_EYE_BEAM_STALKER = 100436,
NPC_RISEN_ARCANIST = 100486,
NPC_INTRO_RISEN_ARCHER = 98275,
NPC_INTRO_RISEN_ARCANIST = 98280,
NPC_INTRP_RISEN_SCOUT = 98691,
NPC_SOUL_TORN_VANGUARD = 100485,
NPC_KURTALOS = 98965,
NPC_LATOSIUS = 98970,
NPC_DANTALIONAX = 99611,
NPC_SOUL_KURTALOS = 101054,
NPC_IMAGE_OF_LATOSIUS = 101028,
NPC_KURTALOS_BLADE_TRIGGER = 100861, //Cast AT 198782
NPC_CLOUD_OF_HYPNOSIS = 100994,
NPC_STINGING_SWARM = 101008,
//Smashspite
NPC_FEL_BAT = 100759,
BOSS_LORD_KURTALOS_RAVENCREST = 94923 BOSS_LORD_KURTALOS_RAVENCREST = 94923
}; };
@@ -0,0 +1,784 @@
/*
* Copyright (C) WowCommunity Project
*
* This SourceCode is NOT free a software. Please hold everything Private
* and read our Terms
*/
#include "black_rook_hold.h"
#include "ScriptMgr.h"
#include "CreatureAIImpl.h"
#include "GameObject.h"
#include "GameObjectAI.h"
#include "Group.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "TemporarySummon.h"
enum Says
{
SAY_AGGRO = 0,
SAY_VENGEFUL_SHEAR = 1,
SAY_DARK_RUSH = 2,
SAY_WARN_DARK_RUSH = 3,
SAY_PHASE_FLY = 4,
SAY_EYE_BEAMS = 5,
SAY_WARN_EYE_BEAMS = 6,
SAY_DEATH = 7,
};
enum Spells
{
SPELL_FURY_POWER_OVERRIDE = 197367,
SPELL_REGEN_POWER = 197394,
SPELL_BRUTAL_GLAIVE = 197546,
SPELL_VENGEFUL_SHEAR = 197418,
SPELL_DARK_RUSH_FILTER = 197478,
SPELL_DARK_RUSH_CHARGE = 197484,
SPELL_PHASE_FLY_JUMP = 197622,
SPELL_EYE_BEAMS = 197674,
SPELL_EYE_BEAMS_AURA = 197696,
SPELL_EYE_BEAMS_AT = 197703,
SPELL_FIXATE_BEAM = 197687,
//Christmas
SPELL_CHRISTMAS_CAP = 220873,
//Other
SPELL_BOULDER_EXPLODE_AT = 222378,
SPELL_BOULDER_EXPLODE_REMOVE = 222388,
SPELL_DRINK_ANCIENT_POTION = 200784,
SPELL_HYPERACTIVE_DUMMY = 201064,
SPELL_HYPERACTIVE_AT = 201063, //Dmg 201062
SPELL_DIZZY_STUN = 201070,
SPELL_INDIGESTION_DUMMY = 200958,
SPELL_INDIGESTION_CHANNEL = 200913,
SPELL_FRENZY_POTION = 201061,
};
enum eEvents
{
EVENT_BRUTAL_GLAIVE = 1,
EVENT_VENGEFUL_SHEAR = 2,
EVENT_DARK_RUSH_1 = 3,
EVENT_DARK_RUSH_2 = 4,
EVENT_SUMMON_ADDS = 5,
EVENT_EYE_BEAMS = 6,
EVENT_PHASE_FLY = 7,
EVENT_PHASE_GROUND = 8,
DATA_ACHIEVEMENT,
EVENT_1,
EVENT_2,
EVENT_3,
};
std::vector<std::pair<uint32, Position>> introSumPos
{
{98706, {3104.32f, 7320.2f, 96.0f, 0.91f}}, //Commander Shemdah'sohn
{98275, {3121.12f, 7335.8f, 86.37f, 1.18f}}, //Risen Archer
{98275, {3114.48f, 7340.4f, 86.37f, 0.73f}}, //Risen Archer
{98275, {3096.66f, 7343.5f, 102.69f, 5.64f}}, //Risen Archer
{98275, {3129.64f, 7319.1f, 102.78f, 2.94f}}, //Risen Archer
{98280, {3114.86f, 7346.0f, 86.50f, 0.20f}}, //Risen Arcanist
{98691, {3125.06f, 7336.8f, 86.46f, 1.68f}}, //Risen Scout
{98691, {3111.49f, 7364.9f, 102.69f, 5.60f}}, //Risen Scout
{98691, {3145.1f, 7340.7f, 102.78f, 2.63f}} //Risen Scout
};
Position const summonsPos[2] =
{
{3105.11f, 7296.94f, 103.28f, 3.14f}, //NPC_RISEN_ARCANIST
{3083.07f, 7313.35f, 103.28f, 4.92f} //NPC_SOUL_TORN_VANGUARD
};
//98696
struct boss_illysanna_ravencrest : public ScriptedAI
{
boss_illysanna_ravencrest(Creature* creature) : ScriptedAI(creature)
{
if (me->IsAlive())
Intro();
}
std::list<ObjectGuid> trashGuidList;
bool phaseTwo = false;
bool achievement = true;
uint8 trashDiedCount = 0;
InstanceScript* instance;
EventMap events;
void Intro()
{
if (instance && instance->GetData(DATA_ILLYSANNA_RAVENCREST) == DONE)
{
me->SetHomePosition(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY(), me->GetHomePosition().GetPositionZ(), 3.6f);
me->SetFacingTo(3.6f);
return;
}
if (instance)
instance->SetData(DATA_ILLYSANNA_RAVENCREST, IN_PROGRESS);
me->SetReactState(REACT_PASSIVE);
me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
for (auto& pair : introSumPos)
{
if (auto trash = me->SummonCreature(pair.first, pair.second))
{
if (trash->GetPositionZ() > 100.0f || trash->GetEntry() == NPC_COMMANDER_SHEMDAHSOHN)
{
trashGuidList.push_back(trash->GetGUID());
trash->SetReactState(REACT_PASSIVE);
trash->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
trash->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
trash->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
}
}
}
}
void Reset() override
{
me->SetPower(POWER_ENERGY, 100);
DoCast(me, SPELL_FURY_POWER_OVERRIDE, true);
DoCast(me, SPELL_REGEN_POWER, true);
me->SetReactState(REACT_AGGRESSIVE);
me->SetCanFly(true);
phaseTwo = false;
achievement = true;
if (!IsCombatMovementAllowed())
SetCombatMovement(true);
}
void JustEngagedWith(Unit* u) override
{
JustEngagedWith(u);
DefaultEvents();
Talk(SAY_AGGRO);
}
void JustDied(Unit* killer) override
{
Talk(SAY_DEATH);
JustDied(killer);
}
void DefaultEvents()
{
events.RescheduleEvent(EVENT_BRUTAL_GLAIVE, 6s);
events.RescheduleEvent(EVENT_VENGEFUL_SHEAR, 9s);
events.RescheduleEvent(EVENT_DARK_RUSH_1, 12s);
}
void SpellHitTarget(WorldObject* target, const SpellInfo* spell) override
{
switch (spell->Id)
{
case SPELL_DARK_RUSH_FILTER:
Talk(SAY_WARN_DARK_RUSH);
break;
case SPELL_VENGEFUL_SHEAR:
DoCast(target->ToUnit(), 197429, true); //debuff: mod damage
break;
case SPELL_EYE_BEAMS:
{
Talk(SAY_WARN_EYE_BEAMS);
if (auto stalker = me->SummonCreature(NPC_EYE_BEAM_STALKER, target->GetPosition(), TEMPSUMMON_TIMED_DESPAWN, 12s))
DoCast(stalker, SPELL_EYE_BEAMS_AURA, true);
break;
}
default:
break;
}
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == EFFECT_MOTION_TYPE)
{
if (id == SPELL_PHASE_FLY_JUMP)
{
Talk(SAY_EYE_BEAMS);
me->GetMotionMaster()->Clear();
me->SetFacingTo(4.05f);
events.RescheduleEvent(EVENT_SUMMON_ADDS, 10s);
events.RescheduleEvent(EVENT_EYE_BEAMS, 20s);
}
if (id == 1)
{
me->SetCanFly(true);
me->SetReactState(REACT_AGGRESSIVE);
DoCast(me, SPELL_REGEN_POWER, true);
phaseTwo = false;
}
}
if (type == POINT_MOTION_TYPE)
{
if (id == SPELL_DARK_RUSH_CHARGE)
events.RescheduleEvent(EVENT_DARK_RUSH_2, 5s);
}
}
void DoAction(int32 const /*action*/) override
{
if (!phaseTwo)
{
phaseTwo = true;
events.RescheduleEvent(EVENT_PHASE_FLY, 5s);
}
}
uint32 GetData(uint32 type) const override
{
if (type == DATA_ACHIEVEMENT)
return achievement;
return 0;
}
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
{
switch (summon->GetEntry())
{
case NPC_RISEN_ARCANIST:
case NPC_SOUL_TORN_VANGUARD:
achievement = false;
break;
case NPC_INTRO_RISEN_ARCHER:
case NPC_INTRO_RISEN_ARCANIST:
case NPC_INTRP_RISEN_SCOUT:
case NPC_COMMANDER_SHEMDAHSOHN:
{
++trashDiedCount;
if (trashDiedCount == 4)
{
for (auto guid : trashGuidList)
{
if (auto trash = ObjectAccessor::GetCreature(*me, guid))
{
Position pos;
float x, y;
trash->GetNearPoint2D(trash, x,y, 15.0f, 0.0f);
pos.m_positionZ = trash->GetPositionZ();
trash->SetHomePosition(pos);
trash->GetMotionMaster()->MoveJump(1, pos, 15.0f, 10.0f, 15.0f);
}
}
for (auto guid : trashGuidList)
{
if (auto trash = ObjectAccessor::GetCreature(*me, guid))
{
trash->SetReactState(REACT_AGGRESSIVE);
trash->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
trash->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
trash->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
trash->AI()->DoZoneInCombat(trash);
}
}
}
else if (trashDiedCount == 9)
{
instance->SetData(DATA_ILLYSANNA_RAVENCREST, DONE);
me->SetHomePosition(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY(), me->GetHomePosition().GetPositionZ(), 3.6f);
me->SetFacingTo(3.6f);
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
}
break;
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_BRUTAL_GLAIVE:
if (auto pTarget = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true, true, -SPELL_BRUTAL_GLAIVE))
DoCast(pTarget, SPELL_BRUTAL_GLAIVE);
else if (auto pTarget = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
DoCast(pTarget, SPELL_BRUTAL_GLAIVE);
events.RescheduleEvent(EVENT_BRUTAL_GLAIVE, 16s);
break;
case EVENT_VENGEFUL_SHEAR:
Talk(SAY_VENGEFUL_SHEAR);
DoCastVictim(SPELL_VENGEFUL_SHEAR);
events.RescheduleEvent(EVENT_VENGEFUL_SHEAR, 12s, 15s);
break;
case EVENT_DARK_RUSH_1:
Talk(SAY_DARK_RUSH);
DoCast(SPELL_DARK_RUSH_FILTER);
for (auto id : { EVENT_BRUTAL_GLAIVE, EVENT_VENGEFUL_SHEAR, EVENT_PHASE_FLY })
events.RescheduleEvent(id, 9s, true);
SetCombatMovement(true);
events.RescheduleEvent(EVENT_DARK_RUSH_1, 30s);
events.RescheduleEvent(EVENT_DARK_RUSH_2, 60s);
break;
case EVENT_DARK_RUSH_2:
if (SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true, true, SPELL_DARK_RUSH_FILTER))
DoCast(me, SPELL_DARK_RUSH_CHARGE, true);
break;
case EVENT_SUMMON_ADDS:
if (me->GetMap()->GetDifficultyID() != DIFFICULTY_LFR && me->GetMap()->GetDifficultyID() != DIFFICULTY_NORMAL)
me->SummonCreature(NPC_RISEN_ARCANIST, summonsPos[0]);
me->SummonCreature(NPC_SOUL_TORN_VANGUARD, summonsPos[1]);
break;
case EVENT_EYE_BEAMS:
{
int8 powerCount = me->GetPower(POWER_ENERGY) - 34;
if (powerCount <= 0)
{
powerCount = 0;
events.RescheduleEvent(EVENT_PHASE_GROUND, 14s);
}
else
events.RescheduleEvent(EVENT_EYE_BEAMS, 13s);
DoCast(SPELL_EYE_BEAMS);
me->SetPower(POWER_ENERGY, powerCount);
break;
}
case EVENT_PHASE_FLY:
Talk(SAY_PHASE_FLY);
events.Reset();
me->AttackStop();
me->RemoveAurasDueToSpell(SPELL_REGEN_POWER);
me->SetCanFly(true);
DoCast(me, SPELL_PHASE_FLY_JUMP, true);
break;
case EVENT_PHASE_GROUND:
DefaultEvents();
DoCast(me, SPELL_FURY_POWER_OVERRIDE, true);
break;
}
}
}
};
//100436
struct npc_illysanna_eye_beam_stalker : public ScriptedAI
{
npc_illysanna_eye_beam_stalker(Creature* creature) : ScriptedAI(creature)
{
me->SetReactState(REACT_PASSIVE);
}
EventMap events;
ObjectGuid targetGuid;
void Reset() override {}
void IsSummonedBy(WorldObject* /*summoner*/) override
{
events.RescheduleEvent(EVENT_1, 5s);
events.RescheduleEvent(EVENT_2, 10s);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
{
damage = 0;
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
if (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_1:
{
if (auto summoner = me->GetOwner())
if (auto target = summoner->GetAI()->SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
{
targetGuid = target->GetGUID();
me->CastSpell(target, SPELL_FIXATE_BEAM, true);
}
events.RescheduleEvent(EVENT_1, 6s);
break;
}
case EVENT_2:
if (auto plrTarget = ObjectAccessor::GetUnit(*me, targetGuid))
me->GetMotionMaster()->MovePoint(1, plrTarget->GetPosition(), false);
events.RescheduleEvent(EVENT_2, 5s);
break;
}
}
}
};
//98706
struct npc_illysanna_commandir : public ScriptedAI
{
npc_illysanna_commandir(Creature* creature) : ScriptedAI(creature)
{
me->SetReactState(REACT_PASSIVE);
}
EventMap events;
void Reset() override
{
events.Reset();
}
void JustEngagedWith(Unit* /*u*/) //override
{
events.ScheduleEvent(EVENT_1, 8s);
events.ScheduleEvent(EVENT_2, 12s);
}
void EnterEvadeMode(EvadeReason /*w*/)
{
me->SetReactState(REACT_AGGRESSIVE);
}
void DoAction(int32 const /*action*/) override
{
Talk(0);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_1:
me->AttackStop();
me->SetReactState(REACT_AGGRESSIVE);
me->CastSpell(me, 200261);
events.RescheduleEvent(EVENT_1, 22s);
break;
case EVENT_2:
DoCast(225998);
events.RescheduleEvent(EVENT_2, 30s);
break;
}
}
}
};
//100486
struct npc_illysanna_trash_generic : public ScriptedAI
{
npc_illysanna_trash_generic(Creature* creature) : ScriptedAI(creature) {}
void Reset() override {}
void JustEngagedWith(Unit* /*u*/) override {}
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoSpellAttackIfReady(197797);
}
};
//111706
struct npc_brh_boulder : public ScriptedAI
{
npc_brh_boulder(Creature* creature) : ScriptedAI(creature)
{
me->SetReactState(REACT_PASSIVE);
}
void Reset()
{
DoCast(me, SPELL_BOULDER_EXPLODE_AT, true);
}
void MovementInform(uint32 type, uint32 /*id*/) override
{
if (type == EFFECT_MOTION_TYPE)
{
me->CastSpell(me, SPELL_BOULDER_EXPLODE_REMOVE, false);
me->DespawnOrUnsummon(100ms);
}
}
void UpdateAI(uint32 /*diff*/) override {}
};
//98792
struct npc_brh_wyrmtongue_scavenger : public ScriptedAI
{
npc_brh_wyrmtongue_scavenger(Creature* creature) : ScriptedAI(creature) {}
ObjectGuid fixateGUID;
uint8 ancientEvent = 0;
uint32 healthPct = 66;
uint32 indigestionTimer = 0;
uint32 hyperactiveTimer = 0;
void Reset()
{
fixateGUID.Clear();
me->SetReactState(REACT_AGGRESSIVE);
indigestionTimer = 0;
hyperactiveTimer = 0;
}
void JustEngagedWith(Unit* /*u*/) override
{
SetAncientEvent(true);
}
void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
{
if (HealthBelowPct(healthPct))
{
healthPct = 0;
me->CastSpell(me, SPELL_DRINK_ANCIENT_POTION);
}
}
void SpellHit(WorldObject* /*caster*/, SpellInfo const* spell) override
{
if (spell->Id == SPELL_DRINK_ANCIENT_POTION && !ancientEvent)
{
ancientEvent = urand(1, 3);
SetAncientEvent();
}
}
void SetAncientEvent(bool JustEngagedWith = false)
{
switch (ancientEvent)
{
case 1:
if (!JustEngagedWith)
Talk(0);
me->AttackStop();
DoCast(me, SPELL_HYPERACTIVE_DUMMY, true);
hyperactiveTimer = 500;
break;
case 2:
DoCast(me, SPELL_INDIGESTION_DUMMY, true);
indigestionTimer = 2000;
break;
case 3:
if (!JustEngagedWith)
DoCast(me, SPELL_FRENZY_POTION, true);
break;
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING | UNIT_STATE_STUNNED))
return;
if (indigestionTimer)
{
if (indigestionTimer <= diff)
{
indigestionTimer = 2000;
if (auto victim = me->GetVictim())
{
if (me->IsWithinMeleeRange(victim))
{
indigestionTimer = 0;
me->AttackStop();
me->CastSpell(me, SPELL_INDIGESTION_CHANNEL);
}
}
}
else
indigestionTimer -= diff;
}
if (hyperactiveTimer)
{
if (hyperactiveTimer <= diff)
{
hyperactiveTimer = 1000;
auto target = ObjectAccessor::GetUnit(*me, fixateGUID);
if (target && target->IsAlive() && target->HasAura(SPELL_HYPERACTIVE_AT, me->GetGUID()))
me->GetMotionMaster()->MovePoint(1, target->GetPosition(), false);
else if (auto target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
{
hyperactiveTimer = 3500;
fixateGUID = target->GetGUID();
me->CastSpell(target, SPELL_HYPERACTIVE_AT);
}
}
else
hyperactiveTimer -= diff;
}
}
};
//197394
class spell_illysanna_periodic_energize : public AuraScript
{
void OnTick(AuraEffect const* /*aurEff*/)
{
auto caster = GetCaster()->ToCreature();
if (!caster || !caster->IsInCombat())
return;
uint8 powerCount = caster->GetPower(POWER_ENERGY);
if (powerCount < 100)
caster->SetPower(POWER_ENERGY, powerCount + 1);
else if (!caster->HasUnitState(UNIT_STATE_CASTING))
caster->AI()->DoAction(true);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_illysanna_periodic_energize::OnTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
//197696
class spell_illysanna_eye_beams : public AuraScript
{
void OnTick(AuraEffect const* /*aurEff*/)
{
if (!GetCaster() || !GetTarget())
return;
GetCaster()->CastSpell(GetTarget(), SPELL_EYE_BEAMS_AT, true);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_illysanna_eye_beams::OnTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
//197484
class spell_illysanna_dark_rush : public SpellScript
{
std::list<WorldObject*> tempTargets;
Position savePos;
void FilterTargets(std::list<WorldObject*>& targets)
{
if (!tempTargets.empty())
{
targets = tempTargets;
return;
}
targets.remove_if([this](WorldObject* object) -> bool
{
if (object == nullptr || !object->IsPlayer() || !object->ToUnit()->HasAura(SPELL_DARK_RUSH_FILTER))
return true;
return false;
});
if (GetCaster() && !targets.empty())
{
targets.resize(1);
if (auto object = targets.front())
{
tempTargets.push_back(object);
savePos = object->GetPosition();
}
}
}
void HandleDummy(SpellEffIndex effectIndex)
{
if (tempTargets.empty())
{
PreventHitEffect(effectIndex);
return;
}
// GetCaster()->GetMotionMaster()->MoveCharge(savePos, 20.0f);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_illysanna_dark_rush::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_illysanna_dark_rush::FilterTargets, EFFECT_2, TARGET_UNIT_DEST_AREA_ENEMY);
OnEffectLaunch += SpellEffectFn(spell_illysanna_dark_rush::HandleDummy, EFFECT_3, SPELL_EFFECT_CREATE_AREATRIGGER);
}
};
//32384
class achievement_adds_more_like_bads : public AchievementCriteriaScript
{
public:
achievement_adds_more_like_bads() : AchievementCriteriaScript("achievement_adds_more_like_bads") { }
bool OnCheck(Player* /*player*/, Unit* target) override
{
if (!target)
return false;
if (auto boss = target->ToCreature())
if (boss->GetMap()->GetDifficultyID() == DIFFICULTY_MYTHIC || boss->GetMap()->GetDifficultyID() == DIFFICULTY_MYTHIC_KEYSTONE)
if (boss->GetAI()->GetData(DATA_ACHIEVEMENT))
return true;
return false;
}
};
void AddSC_boss_illysanna_ravencrest()
{
RegisterCreatureAI(boss_illysanna_ravencrest);
RegisterCreatureAI(npc_illysanna_eye_beam_stalker);
RegisterCreatureAI(npc_illysanna_commandir);
RegisterCreatureAI(npc_illysanna_trash_generic);
RegisterCreatureAI(npc_brh_boulder);
RegisterCreatureAI(npc_brh_wyrmtongue_scavenger);
RegisterSpellScript(spell_illysanna_periodic_energize);
RegisterSpellScript(spell_illysanna_eye_beams);
RegisterSpellScript(spell_illysanna_dark_rush);
new achievement_adds_more_like_bads();
}
@@ -0,0 +1,641 @@
/*
* Copyright (C) WowCommunity Project
*
* This SourceCode is NOT free a software. Please hold everything Private
* and read our Terms
*/
#include "black_rook_hold.h"
#include "TemporarySummon.h"
enum Says
{
//Kurtalos
SAY_AGGRO = 0,
//Latosius
SAY_DARK_BLAST = 0,
SAY_WARN_DREADLORDS_GUILE = 1,
SAY_DREADLORDS_GUILE = 2,
SAY_CLOUD_OF_HYPNOSIS = 3,
};
enum Spells
{
//Kurtalos
//Phase 1
SPELL_UNERRING_SHEAR = 198635,
SPELL_WHIRLING_BLADE = 198641,
SPELL_WHIRLING_BLADE_AT = 198782,
SPELL_SUICIDE = 117624,
//Phase 2
SPELL_KURTALOS_GHOST_VISUAL = 199243,
SPELL_LEGACY_RAVENCREST = 199368,
//Latosius
//Phase 1
SPELL_TELEPORT_1 = 198835,
SPELL_TELEPORT_2 = 199058,
SPELL_SHADOW_BOLT = 198833,
SPELL_DARK_BLAST = 198820,
//Phase 2
SPELL_CONVERSATION = 199239, // Dreadlord Conversation
SPELL_SAP_SOUL = 198961,
SPELL_TRANSFORM = 199064,
SPELL_SHADOW_BOLT_VOLLEY = 202019,
SPELL_CLOUD_OF_HYPNOSIS = 199143,
SPELL_DREADLORDS_GUILE = 199193,
SPELL_BREAK_PLR_TARGETTING = 140562,
SPELL_DARK_OBLITERATION = 199567,
SPELL_DARK_OBLITERATION_AT = 241672,
//Heroic
SPELL_STINGING_SWARM = 201733,
SPELL_ITCHY_STUN = 199168,
};
enum eEvents
{
//Kurtalos
//Phase 1
EVENT_UNERRING_SHEAR = 1,
EVENT_WHIRLING_BLADE = 2,
//Latosius
//Phase 1
EVENT_LATOSIUS_TP = 1,
EVENT_SHADOW_BOLT = 2,
EVENT_DARK_BLAST = 3,
//Phase 2
EVENT_LATOSIUS_TP_2 = 4,
EVENT_SAP_SOUL = 5,
EVENT_TRANSFORM = 6,
EVENT_SHADOW_BOLT_VOLLEY = 7,
EVENT_CLOUD_OF_HYPNOSIS = 8,
EVENT_DREADLORDS_GUILE = 9,
EVENT_SUM_IMAGE = 10,
EVENT_IMAGE_END = 11,
EVENT_STINGING_SWARM = 12, //Heroic
EVENT_1,
EVENT_2,
EVENT_3,
ACTION_1,
};
enum ePhase
{
PHASE_1 = 0,
PHASE_2 = 1,
};
Position const tpPos[12] =
{
{3169.09f, 7432.38f, 271.60f, 5.42f},
{3165.53f, 7421.75f, 271.60f, 5.85f},
{3158.29f, 7414.00f, 271.60f, 0.0f },
{3164.16f, 7395.63f, 271.60f, 0.62f},
{3173.76f, 7387.44f, 271.60f, 1.08f},
{3184.47f, 7383.66f, 271.60f, 1.49f},
{3200.61f, 7390.41f, 271.60f, 2.14f},
{3205.70f, 7400.89f, 271.60f, 2.61f},
{3210.50f, 7409.22f, 271.60f, 3.02f},
{3204.84f, 7427.28f, 271.60f, 3.84f},
{3195.91f, 7430.39f, 271.60f, 4.24f},
{3186.87f, 7436.26f, 271.60f, 4.70f}
};
//98970
struct boss_latosius : public BossAI
{
boss_latosius(Creature* creature) : BossAI(creature, DATA_LORD_KURTALOS_RAVENCREST) {}
bool secondPhase = false;
uint8 imageSumCount = 0;
void Reset() override
{
if (instance->GetData(DATA_LORD_KURTALOS_RAVENCREST_STATE) != PHASE_1)
return;
_Reset();
secondPhase = false;
SetCombatMovement(false);
me->SetReactState(REACT_PASSIVE);
me->SetUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1);
SetEquipmentSlots(false, 65483);
me->SummonCreature(NPC_KURTALOS, 3191.72f, 7423.69f, 270.462f, 0.57f);
}
void JustEngagedWith(Unit* u) //override
{
if (instance->GetData(DATA_LORD_KURTALOS_RAVENCREST_STATE) != PHASE_1)
return;
_JustEngagedWith(u);
if (auto kurtalos = me->FindNearestCreature(NPC_KURTALOS, 30.0f))
kurtalos->AI()->DoZoneInCombat(kurtalos);
events.RescheduleEvent(EVENT_LATOSIUS_TP, 1s);
events.RescheduleEvent(EVENT_DARK_BLAST, 10s);
}
void EnterEvadeMode(EvadeReason /*w*/)
{
if (instance->GetData(DATA_LORD_KURTALOS_RAVENCREST_STATE) != PHASE_1)
instance->SetData(DATA_LORD_KURTALOS_RAVENCREST_STATE, PHASE_1);
BossAI::EnterEvadeMode();
me->UpdateEntry(NPC_LATOSIUS);
me->SetDisplayId(me->GetNativeDisplayId());
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
me->RemoveAurasDueToSpell(SPELL_TRANSFORM);
me->NearTeleportTo(me->GetHomePosition());
me->ClearUnitState(UNIT_STATE_EVADE);
RemoveAuras();
_DespawnAtEvade(15s);
}
bool CheckAura()
{
auto const& players = me->GetMap()->GetPlayers();
if (!players.empty())
for (auto const& itr : players)
if (Player* player = itr.GetSource())
{
if (!player->HasAura(213404))
return false;
}
return true;
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
RemoveAuras();
// for quest need "kill"
auto const& players = me->GetMap()->GetPlayers();
if (!players.empty())
{
for (auto const& itr : players)
{
if (Player* player = itr.GetSource())
player->KilledMonsterCredit(99611);
}
instance->DoUpdateCriteria(CriteriaType::DefeatDungeonEncounter, 1835);
}
if (CheckAura())
{
instance->DoRemoveAurasDueToSpellOnPlayers(213404);
}
}
void RemoveAuras()
{
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_UNERRING_SHEAR);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_LEGACY_RAVENCREST);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_STINGING_SWARM);
}
void DoAction(int32 const action) override
{
if (action == ACTION_1 && instance->GetData(DATA_LORD_KURTALOS_RAVENCREST_STATE) != PHASE_2)
{
instance->SetData(DATA_LORD_KURTALOS_RAVENCREST_STATE, PHASE_2);
events.Reset();
events.RescheduleEvent(EVENT_LATOSIUS_TP_2, 10s);
}
}
void SpellHit(WorldObject* /*caster*/, const SpellInfo* spell) override
{
switch (spell->Id)
{
case SPELL_DREADLORDS_GUILE:
me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
me->SetUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1);
me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
me->SetDisplayId(11686);
DoCast(me, SPELL_BREAK_PLR_TARGETTING, true);
break;
default:
break;
}
}
void SpellHitTarget(WorldObject* target, const SpellInfo* spell) override
{
if (spell->Id == SPELL_SAP_SOUL)
events.RescheduleEvent(EVENT_TRANSFORM, 8s);
if (spell->Id == SPELL_STINGING_SWARM)
{
if (auto sum = target->SummonCreature(NPC_STINGING_SWARM, target->GetPosition()))
sum->EnterVehicle(target->ToUnit());
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_LATOSIUS_TP:
DoCast(me, SPELL_TELEPORT_1, true);
events.RescheduleEvent(EVENT_SHADOW_BOLT, 5s);
break;
case EVENT_SHADOW_BOLT:
DoCast(SPELL_SHADOW_BOLT);
events.RescheduleEvent(EVENT_SHADOW_BOLT, 30s);
break;
case EVENT_DARK_BLAST:
Talk(SAY_DARK_BLAST);
me->CastSpell(me, SPELL_DARK_OBLITERATION_AT, true);
me->CastSpell(me, SPELL_DARK_BLAST, false);
events.CancelEvent(EVENT_SHADOW_BOLT);
events.RescheduleEvent(EVENT_LATOSIUS_TP, 5s);
events.RescheduleEvent(EVENT_DARK_BLAST, 18s);
break;
case EVENT_LATOSIUS_TP_2:
DoCast(me, SPELL_TELEPORT_2, true);
DoCast(me, SPELL_CONVERSATION , true);
events.RescheduleEvent(EVENT_SAP_SOUL, 10s);
break;
case EVENT_SAP_SOUL:
DoCast(me, SPELL_SAP_SOUL, true);
break;
case EVENT_TRANSFORM:
secondPhase = true;
me->UpdateEntry(NPC_DANTALIONAX);
me->SetHealth(me->GetMaxHealth());
DoZoneInCombat();
me->AttackStop();
me->SetReactState(REACT_AGGRESSIVE);
DoCast(me, SPELL_TRANSFORM, true);
SetEquipmentSlots(false, 0, 0, 0);
SetCombatMovement(true);
events.RescheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 14s);
events.RescheduleEvent(EVENT_CLOUD_OF_HYPNOSIS, 26s);
events.RescheduleEvent(EVENT_DREADLORDS_GUILE, 35s);
if (me->GetMap()->GetDifficultyID() != DIFFICULTY_LFR && me->GetMap()->GetDifficultyID() != DIFFICULTY_NORMAL)
events.RescheduleEvent(EVENT_STINGING_SWARM, 19s);
break;
case EVENT_SHADOW_BOLT_VOLLEY:
DoCast(SPELL_SHADOW_BOLT_VOLLEY);
events.RescheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 8s);
break;
case EVENT_CLOUD_OF_HYPNOSIS:
Talk(SAY_CLOUD_OF_HYPNOSIS);
if (auto pTarget = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
DoCast(pTarget, SPELL_CLOUD_OF_HYPNOSIS);
events.RescheduleEvent(EVENT_CLOUD_OF_HYPNOSIS, 32s);
break;
case EVENT_DREADLORDS_GUILE:
me->AttackStop();
imageSumCount = 0;
Talk(SAY_WARN_DREADLORDS_GUILE);
Talk(SAY_DREADLORDS_GUILE);
DoCast(SPELL_DREADLORDS_GUILE);
for (auto id : { EVENT_SHADOW_BOLT_VOLLEY, EVENT_CLOUD_OF_HYPNOSIS, EVENT_STINGING_SWARM })
events.RescheduleEvent(id, 26s, true);
events.RescheduleEvent(EVENT_DREADLORDS_GUILE, 8s);
events.RescheduleEvent(EVENT_SUM_IMAGE, 4s);
break;
case EVENT_SUM_IMAGE:
me->SummonCreature(NPC_IMAGE_OF_LATOSIUS, tpPos[imageSumCount], TEMPSUMMON_TIMED_DESPAWN, 4s);
if (++imageSumCount > 10)
{
events.RescheduleEvent(EVENT_IMAGE_END, 3s);
break;
}
events.RescheduleEvent(EVENT_SUM_IMAGE, 16s);
break;
case EVENT_IMAGE_END:
me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
me->RemoveUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1);
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
me->SetDisplayId(me->GetNativeDisplayId());
me->RemoveAurasDueToSpell(SPELL_DREADLORDS_GUILE);
me->SetReactState(REACT_AGGRESSIVE);
break;
case EVENT_STINGING_SWARM:
if (auto target = SelectTarget(SelectTargetMethod::Random, 0, 90.0f, true, true, -SPELL_STINGING_SWARM))
DoCast(target, SPELL_STINGING_SWARM);
events.RescheduleEvent(EVENT_STINGING_SWARM, 17s);
break;
}
}
}
};
//98965
struct npc_kurtalos_ravencrest : public ScriptedAI
{
npc_kurtalos_ravencrest(Creature* creature) : ScriptedAI(creature)
{
instance = me->GetInstanceScript();
}
InstanceScript* instance;
EventMap events;
bool secondPhase = false;
void Reset() override
{
secondPhase = false;
}
void JustEngagedWith(Unit* /*u*/) override
{
Talk(SAY_AGGRO); //Fiends, you shall never have our world!
if (me->GetOwner())
if (auto latosius = me->GetOwner()->ToCreature())
latosius->AI()->DoZoneInCombat(latosius);
events.RescheduleEvent(EVENT_UNERRING_SHEAR, 6s);
events.RescheduleEvent(EVENT_WHIRLING_BLADE, 10s);
}
void EnterEvadeMode(EvadeReason /*w*/)
{
if (instance->GetData(DATA_LORD_KURTALOS_RAVENCREST_STATE) != PHASE_1)
instance->SetData(DATA_LORD_KURTALOS_RAVENCREST_STATE, PHASE_1);
if (me->GetOwner())
if (auto latosius = me->GetOwner()->ToCreature())
latosius->AI()->EnterEvadeMode();
}
void JustDied(Unit* /*killer*/) override
{
if (auto owner = me->GetOwner())
owner->SummonCreature(NPC_SOUL_KURTALOS, me->GetPosition());
}
void SpellHitTarget(WorldObject* target, const SpellInfo* spell) override
{
if (spell->Id == SPELL_WHIRLING_BLADE)
if (auto blade = me->SummonCreature(NPC_KURTALOS_BLADE_TRIGGER, me->GetPosition(), TEMPSUMMON_TIMED_DESPAWN, 30s))
{
blade->AI()->SetGUID(target->GetGUID(), 0);
blade->GetMotionMaster()->MovePoint(1, target->GetPosition());
}
}
void SpellHit(WorldObject* /*caster*/, const SpellInfo* spell) override
{
if (spell->Id == SPELL_SAP_SOUL)
me->CastSpell(me, SPELL_SUICIDE, true);
}
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
{
if (damage >= me->GetHealth() || me->HealthBelowPct(20))
{
if (!secondPhase)
{
secondPhase = true;
me->AttackStop();
events.Reset();
if (auto latosius = me->GetOwner())
latosius->GetAI()->DoAction(ACTION_1);
}
if (attacker != me)
damage = 0;
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_UNERRING_SHEAR:
DoCastVictim(SPELL_UNERRING_SHEAR);
events.RescheduleEvent(EVENT_UNERRING_SHEAR, 13s);
break;
case EVENT_WHIRLING_BLADE:
if (Unit* pTarget = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true))
DoCast(pTarget, SPELL_WHIRLING_BLADE);
events.RescheduleEvent(EVENT_WHIRLING_BLADE, 10s);
break;
}
}
}
};
//101054 - Soul, 100861 - Blade Trigger, 101028 - Image of Latosius
struct npc_kurtalos_trigger : public ScriptedAI
{
npc_kurtalos_trigger(Creature* creature) : ScriptedAI(creature)
{
instance = me->GetInstanceScript();
me->SetFaction(14);
me->SetReactState(REACT_PASSIVE);
me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
me->SetUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1);
}
InstanceScript* instance;
EventMap events;
Position pos[2];
void Reset() override {}
void IsSummonedBy(WorldObject* /*summoner*/) override
{
if (instance->GetBossState(DATA_LORD_KURTALOS_RAVENCREST) != IN_PROGRESS)
{
me->DespawnOrUnsummon();
return;
}
switch (me->GetEntry())
{
case NPC_KURTALOS_BLADE_TRIGGER:
pos[0] = me->GetPosition();
DoCast(me, SPELL_WHIRLING_BLADE_AT, true);
break;
case NPC_SOUL_KURTALOS:
me->SetFaction(35);
DoCast(me, SPELL_KURTALOS_GHOST_VISUAL, true);
events.RescheduleEvent(EVENT_3, 24s);
break;
case NPC_IMAGE_OF_LATOSIUS:
me->CastSpell(me, SPELL_DARK_OBLITERATION_AT, true);
me->CastSpell(me, SPELL_DARK_OBLITERATION, false);
break;
default:
break;
}
}
void MovementInform(uint32 type, uint32 id) override
{
if (type != POINT_MOTION_TYPE)
return;
if (id == 1)
events.RescheduleEvent(EVENT_1, 20s);
if (id == 2)
events.RescheduleEvent(EVENT_2, 20s);
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
if (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_1:
if (instance->GetBossState(DATA_LORD_KURTALOS_RAVENCREST) != IN_PROGRESS)
{
me->DespawnOrUnsummon();
return;
}
me->GetMotionMaster()->MovePoint(2, pos[0], false);
break;
case EVENT_2:
if (instance->GetBossState(DATA_LORD_KURTALOS_RAVENCREST) != IN_PROGRESS)
{
me->DespawnOrUnsummon();
return;
}
me->GetMotionMaster()->MovePoint(1, pos[1], false);
break;
case EVENT_3:
if (instance->GetBossState(DATA_LORD_KURTALOS_RAVENCREST) == IN_PROGRESS)
me->CastSpell(me, SPELL_LEGACY_RAVENCREST, true);
me->DespawnOrUnsummon(20s);
break;
}
}
}
};
//101008
struct npc_kurtalos_stinging_swarm : public ScriptedAI
{
npc_kurtalos_stinging_swarm(Creature* creature) : ScriptedAI(creature)
{
instance = me->GetInstanceScript();
me->SetReactState(REACT_PASSIVE);
}
InstanceScript* instance;
uint16 checkTimer = 0;
void Reset() override
{
checkTimer = 200;
}
void JustDied(Unit* /*killer*/) override
{
if (auto summoner = me->GetOwner())
summoner->RemoveAurasDueToSpell(SPELL_STINGING_SWARM);
}
void UpdateAI(uint32 diff) override
{
if (checkTimer)
{
if (checkTimer <= diff)
{
if (instance->GetBossState(DATA_LORD_KURTALOS_RAVENCREST) != IN_PROGRESS)
{
me->DespawnOrUnsummon();
return;
}
checkTimer = 200;
}
else
checkTimer -= diff;
}
}
};
//198835
class spell_latosius_random_teleport : public SpellScript
{
void HandleScriptEffect(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
if (!GetCaster())
return;
uint8 rand = urand(0, 11);
GetCaster()->NearTeleportTo(tpPos[rand].GetPositionX(), tpPos[rand].GetPositionY(), tpPos[rand].GetPositionZ(), tpPos[rand].GetOrientation());
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_latosius_random_teleport::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_TELEPORT_UNITS);
}
};
//201733
class spell_kurtalos_stinging_swarm : public AuraScript
{
void OnTick(AuraEffect const* /*auraEffect*/)
{
if (GetUnitOwner())
{
if (urand(0, 100) <= 31)
GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_ITCHY_STUN, true);
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_kurtalos_stinging_swarm::OnTick, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE);
}
};
void AddSC_boss_lord_kurtalos_ravencrest()
{
RegisterCreatureAI(boss_latosius);
RegisterCreatureAI(npc_kurtalos_ravencrest);
RegisterCreatureAI(npc_kurtalos_trigger);
RegisterCreatureAI(npc_kurtalos_stinging_swarm);
RegisterSpellScript(spell_latosius_random_teleport);
RegisterSpellScript(spell_kurtalos_stinging_swarm);
}
@@ -0,0 +1,317 @@
/*
* Copyright (C) WowCommunity Project
*
* This SourceCode is NOT free a software. Please hold everything Private
* and read our Terms
*/
#include "black_rook_hold.h"
#include "TemporarySummon.h"
enum Says
{
SAY_AGGRO = 0,
SAY_HATEFUL_GAZE = 1,
SAY_WARN_HATEFUL_GAZE = 2,
SAY_HATEFUL_GAZE_CHARGE = 3,
SAY_EARTHSHAKING_STOMP = 4,
SAY_BRUTAL_HAYMAKER = 5,
SAY_DEATH = 6,
};
enum Spells
{
SPELL_ZERO_REGEN = 72242,
SPELL_BRUTALITY_PROC = 198114,
SPELL_EARTHSHAKING_STOMP = 198073,
SPELL_BRUTAL_HAYMAKER = 198245,
//Heroic
SPELL_HATEFUL_GAZE = 198079,
SPELL_HATEFUL_CHARGE = 198250,
SPELL_HATEFUL_CHARGE_DMG = 198080,
SPELL_HATEFUL_CHARGE_DEBUF = 224188,
SPELL_FEL_VOMIT = 198446,
SPELL_FEL_VOMIT_DMG = 198499,
//Other
SPELL_SIC_BATS = 203163,
};
enum eEvents
{
EVENT_EARTHSHAKING_STOMP = 1,
EVENT_FEL_ATTACK = 2,
EVENT_HATEFUL_GAZE = 3,
};
Position const felPos[10] =
{
{3377.12f, 7379.05f, 260.46f}, //100759
{3405.04f, 7360.28f, 250.10f},
{3410.22f, 7311.27f, 250.10f},
{3392.56f, 7317.72f, 260.46f},
{3379.99f, 7295.96f, 268.62f},
{3388.76f, 7284.25f, 237.00f},
{3257.77f, 7188.85f, 255.80f},
{3352.13f, 7259.52f, 251.29f},
{3206.34f, 7261.78f, 255.80f},
{3267.14f, 7182.61f, 244.89f}
};
Position const centrPos = { 3269.27f, 7289.28f, 231.47f };
//98949
struct boss_smashspite_the_hateful : public BossAI
{
boss_smashspite_the_hateful(Creature* creature) : BossAI(creature, DATA_SMASHPITE_THE_HATEFUL) {}
ObjectGuid felbatContainer[10];
std::list<uint32> felTimer;
void Reset() override
{
_Reset();
DoCast(me, SPELL_ZERO_REGEN, true);
DoCast(me, SPELL_BRUTALITY_PROC, true);
me->SetPower(POWER_ENERGY, 0);
me->SetReactState(REACT_AGGRESSIVE);
for (uint8 i = 0; i < 10; ++i)
{
if (auto summon = me->SummonCreature(NPC_FEL_BAT, felPos[i]))
felbatContainer[i] = summon->GetGUID();
}
}
void JustEngagedWith(Unit* who) //override
{
_JustEngagedWith(who);
Talk(SAY_AGGRO);
felTimer = { 25000, 18000, 14000, 8000 };
events.RescheduleEvent(EVENT_EARTHSHAKING_STOMP, 12s);
events.RescheduleEvent(EVENT_FEL_ATTACK, 25s);
if (me->GetMap()->GetDifficultyID() != DIFFICULTY_LFR && me->GetMap()->GetDifficultyID() != DIFFICULTY_NORMAL)
events.RescheduleEvent(EVENT_HATEFUL_GAZE, 6s);
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
DoCast(me, 205271, true);
instance->instance->SummonCreature(102094, Position(3191.87f, 7364.25f, 223.95f, 5.36f));
instance->instance->SummonCreature(102095, Position(3196.1f, 7367.85f, 223.96f, 5.38f));
}
void SpellHitTarget(WorldObject* target, const SpellInfo* spell) override
{
if (spell->Id == SPELL_HATEFUL_CHARGE_DMG)
{
DoCast(target->ToUnit(), SPELL_HATEFUL_CHARGE_DEBUF, true);
me->StopMoving();
me->AttackStop();
me->SetReactState(REACT_AGGRESSIVE);
}
}
void MovementInform(uint32 type, uint32 id) override
{
if (type != POINT_MOTION_TYPE)
return;
if (id == SPELL_HATEFUL_CHARGE)
me->SetReactState(REACT_AGGRESSIVE);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (me->GetDistance(centrPos) >= 30.0f)
{
EnterEvadeMode();
return;
}
if (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_EARTHSHAKING_STOMP:
Talk(SAY_EARTHSHAKING_STOMP);
DoCast(SPELL_EARTHSHAKING_STOMP);
events.RescheduleEvent(EVENT_EARTHSHAKING_STOMP, 17s);
break;
case EVENT_FEL_ATTACK:
if (auto fel = ObjectAccessor::GetCreature(*me, felbatContainer[urand(0, 9)]))
fel->AI()->DoAction(true);
if (me->GetMap()->GetDifficultyID() == DIFFICULTY_MYTHIC || me->GetMap()->GetDifficultyID() == DIFFICULTY_MYTHIC_KEYSTONE)
{
if (felTimer.size() > 1)
felTimer.pop_front();
events.RescheduleEvent(EVENT_FEL_ATTACK, 10s);
}
else
events.RescheduleEvent(EVENT_FEL_ATTACK, 25s);
break;
case EVENT_HATEFUL_GAZE:
if (auto target = SelectTarget(SelectTargetMethod::MaxDistance, 0, 100.0f, true))
{
Talk(SAY_HATEFUL_GAZE);
Talk(SAY_WARN_HATEFUL_GAZE);
me->StopMoving();
me->AttackStop();
me->CastSpell(target, SPELL_HATEFUL_GAZE, false);
events.RescheduleEvent(EVENT_EARTHSHAKING_STOMP, 10s);
}
events.RescheduleEvent(EVENT_HATEFUL_GAZE, 25s);
break;
}
}
}
};
//100759
struct npc_smashspite_fel_bat : public ScriptedAI
{
npc_smashspite_fel_bat(Creature* creature) : ScriptedAI(creature)
{
me->SetReactState(REACT_PASSIVE);
}
void Reset() override {}
void DoAction(int32 const /*action*/) override
{
me->CastSpell(me, SPELL_FEL_VOMIT);
}
void UpdateAI(uint32 /*diff*/) override {}
};
//102781
struct npc_brh_fel_bat : public ScriptedAI
{
npc_brh_fel_bat(Creature* creature) : ScriptedAI(creature) {}
ObjectGuid targetGUID;
bool wpRun = false;
uint32 despawnTimer = 0;
uint32 findTargetTimer = 0;
void Reset() override
{
me->SetReactState(REACT_AGGRESSIVE);
targetGUID.Clear();
if (me->IsSummon() && !wpRun)
{
me->GetMotionMaster()->MovePath(10278100, frand(-3.0f, 3.0f));
despawnTimer = 60000;
}
}
void SpellHit(WorldObject* /*caster*/, SpellInfo const* spell) override
{
if (spell->Id == SPELL_SIC_BATS && targetGUID.IsEmpty())
{
me->AttackStop();
findTargetTimer = 200;
}
}
void UpdateAI(uint32 diff) override
{
if (despawnTimer)
{
if (despawnTimer <= diff)
{
despawnTimer = 0;
if (!me->IsInCombat())
me->DespawnOrUnsummon();
else
despawnTimer = 5000;
}
else
despawnTimer -= diff;
}
if (findTargetTimer)
{
if (findTargetTimer <= diff)
{
findTargetTimer = 0;
auto target = me->GetVictim();
if (target && target->HasAura(SPELL_SIC_BATS))
findTargetTimer = 1000;
else if (auto target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true, true, SPELL_SIC_BATS))
{
targetGUID = target->GetGUID();
AttackStart(target);
}
else
{
targetGUID.Clear();
me->SetReactState(REACT_AGGRESSIVE);
}
}
else
findTargetTimer -= diff;
}
if (!UpdateVictim())
return;
}
};
//198114
class spell_smashpite_brutality_proc : public AuraScript
{
void OnProc(AuraEffect* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
{
auto caster = GetCaster()->ToCreature();
if (!caster || caster->HasUnitState(UNIT_STATE_CASTING))
return;
uint8 powerCount = caster->GetPower(POWER_ENERGY);
if (powerCount < 100)
{
if (caster->GetMap()->GetDifficultyID() == DIFFICULTY_MYTHIC|| caster->GetMap()->GetDifficultyID() == DIFFICULTY_MYTHIC_KEYSTONE)
caster->SetPower(POWER_ENERGY, powerCount + 10);
else
caster->SetPower(POWER_ENERGY, powerCount + urand(6, 9));
}
else if (caster->GetReactState() == REACT_AGGRESSIVE && caster->GetVictim())
{
caster->AI()->Talk(SAY_BRUTAL_HAYMAKER);
caster->CastSpell(caster->GetVictim(), SPELL_BRUTAL_HAYMAKER);
}
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_smashpite_brutality_proc::OnProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
void AddSC_boss_smashspite_the_hateful()
{
RegisterCreatureAI(boss_smashspite_the_hateful);
RegisterCreatureAI(npc_smashspite_fel_bat);
RegisterCreatureAI(npc_brh_fel_bat);
RegisterSpellScript(spell_smashpite_brutality_proc);
}
@@ -29,8 +29,12 @@ void AddSC_boss_guarm();
void AddSC_instance_trial_of_valor(); void AddSC_instance_trial_of_valor();
// Black Rook Hold // Black Rook Hold
void AddSC_black_rook_hold();
void AddSC_boss_amalgam_of_souls(); void AddSC_boss_amalgam_of_souls();
void AddSC_instance_black_rook_hold(); void AddSC_instance_black_rook_hold();
void AddSC_boss_illysanna_ravencrest();
void AddSC_boss_lord_kurtalos_ravencrest();
void AddSC_boss_smashspite_the_hateful();
// Neltharion's Lair // Neltharion's Lair
void AddSC_boss_rokmora(); void AddSC_boss_rokmora();
@@ -76,8 +80,13 @@ void AddBrokenIslesScripts()
AddSC_instance_trial_of_valor(); AddSC_instance_trial_of_valor();
// Black Rook Hold // Black Rook Hold
AddSC_black_rook_hold();
AddSC_boss_amalgam_of_souls(); AddSC_boss_amalgam_of_souls();
AddSC_instance_black_rook_hold(); AddSC_instance_black_rook_hold();
AddSC_boss_illysanna_ravencrest();
AddSC_boss_lord_kurtalos_ravencrest();
AddSC_boss_smashspite_the_hateful();
// Neltharion's Lair // Neltharion's Lair
AddSC_boss_rokmora(); AddSC_boss_rokmora();