Priority of the sacred flame

This commit is contained in:
luis
2026-09-18 17:24:33 -03:00
parent c4c374f027
commit 61e5da7d30
7 changed files with 616 additions and 238 deletions
@@ -19,124 +19,138 @@
enum Spells
{
SPELL_VINDICTIVE_WRATH = 422969,
SPELL_CASTIGATORS_SHIELD = 423015,
SPELL_CASTIGATORS_DETONATION = 423019,
SPELL_BURNING_LIGHT = 423051,
SPELL_START_ENERGY = 454834,
SPELL_ENERGIZE = 422963,
SPELL_HAMMER_OF_PURITY = 423062,
SPELL_HAMMER_SPIRAL = 423076
SPELL_HAMMER_OF_PURITY_SPIN = 423076,
SPELL_HAMMER_OF_PURITY_BOUNCE = 423072,
SPELL_BURNING_LIGHT = 423051,
SPELL_CASTIGATORS_SHIELD = 423015,
SPELL_CASTIGATORS_DETONATION = 423018,
SPELL_CASTIGATORS_EXPLOSION = 423019,
SPELL_VINDICTIVE_WRATH = 422969,
};
enum Events
{
EVENT_CASTIGATORS_SHIELD = 1,
EVENT_HAMMER_OF_PURITY = 1,
EVENT_HAMMER_OF_PURITY_SPIN,
EVENT_BURNING_LIGHT,
EVENT_HAMMER_OF_PURITY,
EVENT_CHECK_ENERGY
EVENT_CASTIGATORS_SHIELD,
EVENT_CASTIGATORS_DETONATION,
EVENT_CASTIGATORS_EXPLOSION,
EVENT_CHECK_ENERGY,
EVENT_VINDICTIVE_WRATH,
};
// 207939 - Baron Braunpyke
struct boss_baron_braunpyke : public BossAI
{
boss_baron_braunpyke(Creature* creature) : BossAI(creature, DATA_BARON_BRAUNPYKE)
{
Initialize();
}
void Initialize()
{
_vindictiveWrathActive = false;
_holyPower = 0;
}
boss_baron_braunpyke(Creature* creature) : BossAI(creature, DATA_BARON_BRAUNPYKE), _energy(0) { }
void Reset() override
{
_Reset();
Initialize();
BossAI::Reset();
_energy = 0;
_detonationTargets.clear();
}
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
events.ScheduleEvent(EVENT_CASTIGATORS_SHIELD, 10s);
events.ScheduleEvent(EVENT_BURNING_LIGHT, 15s);
events.ScheduleEvent(EVENT_HAMMER_OF_PURITY, 20s);
events.ScheduleEvent(EVENT_CHECK_ENERGY, 2s);
DoCastSelf(SPELL_START_ENERGY, true);
DoCastSelf(SPELL_ENERGIZE, true);
events.ScheduleEvent(EVENT_HAMMER_OF_PURITY, 10s);
events.ScheduleEvent(EVENT_BURNING_LIGHT, 19s);
events.ScheduleEvent(EVENT_CASTIGATORS_SHIELD, 24s);
events.ScheduleEvent(EVENT_CHECK_ENERGY, 1s);
}
void OnSpellCast(SpellInfo const* spell) override
// The Baron shields his two Arathi companions; fall back to players when solo.
std::vector<Unit*> SelectShieldTargets()
{
if (spell->Id == SPELL_BURNING_LIGHT)
events.RescheduleEvent(EVENT_BURNING_LIGHT, 10s);
std::vector<Unit*> targets;
if (targets.size() < 2)
{
std::list<Unit*> players;
SelectTargetList(players, uint32(2 - targets.size()), SelectTargetMethod::Random, 0, 100.0f, true);
targets.insert(targets.end(), players.begin(), players.end());
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
return targets;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
void ExecuteEvent(uint32 eventId) override
{
switch (eventId)
{
case EVENT_CHECK_ENERGY:
if (_holyPower >= 100)
case EVENT_HAMMER_OF_PURITY:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
{
DoCastSelf(SPELL_VINDICTIVE_WRATH);
_vindictiveWrathActive = true;
_holyPower = 0;
_hammerPosition = target->GetPosition();
me->CastSpell(_hammerPosition, SPELL_HAMMER_OF_PURITY, false);
events.ScheduleEvent(EVENT_HAMMER_OF_PURITY_SPIN, 2s);
}
events.Repeat(2s);
events.Repeat(22s);
break;
case EVENT_HAMMER_OF_PURITY_SPIN:
me->CastSpell(_hammerPosition, SPELL_HAMMER_OF_PURITY_SPIN, true);
me->CastSpell(_hammerPosition, SPELL_HAMMER_OF_PURITY_BOUNCE, true);
break;
case EVENT_BURNING_LIGHT:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
me->CastSpell(target->GetPosition(), SPELL_BURNING_LIGHT, false);
events.Repeat(30s);
break;
case EVENT_CASTIGATORS_SHIELD:
{
uint8 targetCount = _vindictiveWrathActive ? 5 : 3;
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f))
_detonationTargets.clear();
for (Unit* target : SelectShieldTargets())
{
std::list<Unit*> targets;
SelectTargetList(targets, targetCount, SelectTargetMethod::Random, 0, 40.0f);
for (Unit* target : targets)
{
DoCast(target, SPELL_CASTIGATORS_SHIELD);
me->CastSpell(target->GetPosition(), SPELL_CASTIGATORS_DETONATION, true);
DoCast(target, SPELL_CASTIGATORS_SHIELD, true);
_detonationTargets.push_back(target->GetGUID());
}
if (!_detonationTargets.empty())
{
events.ScheduleEvent(EVENT_CASTIGATORS_DETONATION, 1s);
events.ScheduleEvent(EVENT_CASTIGATORS_EXPLOSION, 5s);
}
events.Repeat(25s);
break;
}
case EVENT_BURNING_LIGHT:
{
DoCastVictim(SPELL_BURNING_LIGHT, true);
events.Repeat(30s);
case EVENT_CASTIGATORS_DETONATION:
for (ObjectGuid guid : _detonationTargets)
if (Unit* target = ObjectAccessor::GetUnit(*me, guid))
me->CastSpell(target->GetPosition(), SPELL_CASTIGATORS_DETONATION, true);
break;
}
case EVENT_HAMMER_OF_PURITY:
{
uint8 targetCount = _vindictiveWrathActive ? 5 : 3;
for (uint8 i = 0; i < targetCount; ++i)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f))
{
DoCast(target, SPELL_HAMMER_OF_PURITY);
DoCast(target, SPELL_HAMMER_SPIRAL);
}
}
events.Repeat(35s);
case EVENT_CASTIGATORS_EXPLOSION:
for (ObjectGuid guid : _detonationTargets)
if (Unit* target = ObjectAccessor::GetUnit(*me, guid))
me->CastSpell(target->GetPosition(), SPELL_CASTIGATORS_EXPLOSION, true);
break;
case EVENT_CHECK_ENERGY:
_energy += 2;
if (_energy >= 100)
{
_energy = 0;
events.ScheduleEvent(EVENT_VINDICTIVE_WRATH, 0ms);
}
events.Repeat(1s);
break;
case EVENT_VINDICTIVE_WRATH:
DoCastSelf(SPELL_VINDICTIVE_WRATH);
break;
default:
break;
}
}
}
private:
bool _vindictiveWrathActive;
uint8 _holyPower;
uint32 _energy;
Position _hammerPosition;
std::vector<ObjectGuid> _detonationTargets;
};
void AddSC_boss_baron_braunpyke()
@@ -20,97 +20,80 @@
enum Spells
{
SPELL_STRENGTH_IN_NUMBERS = 424626,
SPELL_SAVAGE_MAULING = 447439,
SPELL_BATTLE_CRY = 424419,
SPELL_PIERCE_ARMOR = 424414,
SPELL_HURL_SPEAR = 447272
SPELL_EARTHSHATTERING_SPEAR = 1238780,
SPELL_EARTHSHATTERING_SPEAR_IMPACT = 1238779,
SPELL_EARTHSHATTERING_SPEAR_DAMAGE = 1238782,
SPELL_BATTLE_CRY = 424419,
SPELL_SAVAGE_MAULING = 447429,
SPELL_SAVAGE_MAULING_STRIKE = 447439,
};
enum Events
{
EVENT_SAVAGE_MAULING = 1,
EVENT_PIERCE_ARMOR = 1,
EVENT_EARTHSHATTERING_SPEAR,
EVENT_EARTHSHATTERING_SPEAR_IMPACT,
EVENT_BATTLE_CRY,
EVENT_HURL_SPEAR,
EVENT_PIERCE_ARMOR
EVENT_SAVAGE_MAULING,
};
// 207946 - Captain Dailcry
struct boss_captain_dailcry : public BossAI
{
boss_captain_dailcry(Creature* creature) : BossAI(creature, DATA_CAPTAIN_DAILCRY)
{
Initialize();
}
void Initialize()
{
_emberShieldBroken = false;
}
void Reset() override
{
_Reset();
Initialize();
}
boss_captain_dailcry(Creature* creature) : BossAI(creature, DATA_CAPTAIN_DAILCRY) { }
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
events.ScheduleEvent(EVENT_BATTLE_CRY, 10s);
events.ScheduleEvent(EVENT_PIERCE_ARMOR, 15s);
events.ScheduleEvent(EVENT_HURL_SPEAR, 20s);
events.ScheduleEvent(EVENT_SAVAGE_MAULING, 25s);
events.ScheduleEvent(EVENT_PIERCE_ARMOR, 3500ms);
events.ScheduleEvent(EVENT_EARTHSHATTERING_SPEAR, 3s);
events.ScheduleEvent(EVENT_BATTLE_CRY, 7s);
events.ScheduleEvent(EVENT_SAVAGE_MAULING, 20s);
}
void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
{
// Logic for breaking Ember's shield during Savage Mauling
if (!_emberShieldBroken && me->HasAura(SPELL_SAVAGE_MAULING))
{
// Shield break logic here
_emberShieldBroken = true;
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
void ExecuteEvent(uint32 eventId) override
{
switch (eventId)
{
case EVENT_BATTLE_CRY:
DoCastAOE(SPELL_BATTLE_CRY);
events.Repeat(30s);
break;
case EVENT_PIERCE_ARMOR:
DoCastVictim(SPELL_PIERCE_ARMOR);
events.Repeat(15s);
events.Repeat(13s);
break;
case EVENT_HURL_SPEAR:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f))
DoCast(target, SPELL_HURL_SPEAR);
events.Repeat(20s);
case EVENT_EARTHSHATTERING_SPEAR:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
{
_spearPosition = target->GetPosition();
me->CastSpell(_spearPosition, SPELL_EARTHSHATTERING_SPEAR, false);
me->CastSpell(_spearPosition, SPELL_EARTHSHATTERING_SPEAR_IMPACT, true);
events.ScheduleEvent(EVENT_EARTHSHATTERING_SPEAR_IMPACT, 3s);
}
events.Repeat(33s);
break;
case EVENT_EARTHSHATTERING_SPEAR_IMPACT:
me->CastSpell(_spearPosition, SPELL_EARTHSHATTERING_SPEAR_DAMAGE, true);
break;
case EVENT_BATTLE_CRY:
DoCastAOE(SPELL_BATTLE_CRY);
events.Repeat(33s);
break;
case EVENT_SAVAGE_MAULING:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f))
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
{
Position pos = target->GetPosition();
me->GetMotionMaster()->MoveCharge(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ());
DoCast(target, SPELL_SAVAGE_MAULING);
events.Repeat(25s);
me->CastSpell(me, SPELL_SAVAGE_MAULING_STRIKE, true);
}
events.Repeat(33s);
break;
default:
break;
}
}
}
private:
bool _emberShieldBroken;
Position _spearPosition;
};
void AddSC_boss_captain_dailcry()
@@ -19,124 +19,174 @@
enum Spells
{
SPELL_THE_SACRED_FLAME = 425544,
SPELL_SANCTIFIED_GROUND = 425556,
SPELL_BARRIER_OF_LIGHT = 423588,
SPELL_EMBRACE_THE_LIGHT = 423665,
SPELL_INNER_FIRE = 423539,
SPELL_HOLY_FLAME = 451606,
SPELL_BLINDING_LIGHT = 1242783,
SPELL_STOKE_THE_FLAME = 460838,
SPELL_STOKE_THE_FLAME_2 = 460871,
SPELL_STOKE_THE_FLAME_REKINDLE = 444609,
SPELL_STOKE_THE_FLAME_REKINDLE_2 = 444611,
SPELL_HOLY_SMITE = 423536,
SPELL_BLINDING_LIGHT = 428169,
// Arathi Neophyte
SPELL_OVERWHELMING_POWER = 425022
SPELL_PURIFY = 444546,
SPELL_PURIFY_PULSE = 425554,
SPELL_HOLY_FLAME = 451605,
SPELL_HOLY_FLAME_IMPACT = 451606,
SPELL_INNER_FIRE = 444608,
SPELL_INNER_FIRE_AURA = 423547,
SPELL_SANCTIFIED_GROUND = 425556,
SPELL_CLEAR_ENERGY = 448497,
SPELL_EMBRACE_THE_LIGHT_BIND = 423682,
SPELL_BARRIER_OF_LIGHT = 423588,
SPELL_EMBRACE_THE_LIGHT = 423664,
SPELL_EMBRACE_THE_LIGHT_TICK = 423665,
};
enum Events
{
EVENT_SACRED_FLAME = 1,
EVENT_HOLY_SMITE = 1,
EVENT_PURIFY,
EVENT_HOLY_FLAME,
EVENT_HOLY_SMITE,
EVENT_INNER_FIRE,
EVENT_BLINDING_LIGHT,
EVENT_EMBRACE_THE_LIGHT,
EVENT_SUMMON_NEOPHYTES
EVENT_SANCTIFIED_GROUND,
EVENT_CHECK_ENERGY,
EVENT_INTERMISSION_START,
EVENT_EMBRACE_CHANNEL,
EVENT_INTERMISSION_END,
};
// 207940 - Prioress Murrpray
struct boss_prioress_murrpray : public BossAI
{
boss_prioress_murrpray(Creature* creature) : BossAI(creature, DATA_PRIORESS_MURRPRAY)
{
Initialize();
}
void Initialize()
{
_barrierPhase = false;
}
boss_prioress_murrpray(Creature* creature) : BossAI(creature, DATA_PRIORESS_MURRPRAY), _energy(0), _intermission(false) { }
void Reset() override
{
_Reset();
Initialize();
BossAI::Reset();
_energy = 0;
_intermission = false;
me->SetPowerType(POWER_ENERGY);
me->SetMaxPower(POWER_ENERGY, 100);
}
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
events.ScheduleEvent(EVENT_SACRED_FLAME, 10s);
events.ScheduleEvent(EVENT_HOLY_FLAME, 15s);
events.ScheduleEvent(EVENT_HOLY_SMITE, 5s);
events.ScheduleEvent(EVENT_INNER_FIRE, 20s);
me->SetPower(POWER_ENERGY, 0);
if (IsHeroic() || IsMythic())
events.ScheduleEvent(EVENT_BLINDING_LIGHT, 25s);
DoCastSelf(SPELL_BLINDING_LIGHT, true);
DoCastSelf(SPELL_STOKE_THE_FLAME, true);
DoCastSelf(SPELL_STOKE_THE_FLAME_2, true);
ScheduleBuildEvents();
events.ScheduleEvent(EVENT_CHECK_ENERGY, 1s);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
void ScheduleBuildEvents()
{
if (!_barrierPhase && me->HealthBelowPctDamaged(50, damage))
events.ScheduleEvent(EVENT_HOLY_SMITE, 2s);
events.ScheduleEvent(EVENT_PURIFY, 12s);
events.ScheduleEvent(EVENT_HOLY_FLAME, 16s);
events.ScheduleEvent(EVENT_INNER_FIRE, 22s);
events.ScheduleEvent(EVENT_SANCTIFIED_GROUND, 30s);
}
void StartIntermission()
{
_barrierPhase = true;
events.Reset();
DoCastSelf(SPELL_BARRIER_OF_LIGHT);
events.ScheduleEvent(EVENT_EMBRACE_THE_LIGHT, 2s);
events.ScheduleEvent(EVENT_SUMMON_NEOPHYTES, 3s);
_intermission = true;
events.CancelEvent(EVENT_CHECK_ENERGY);
DoCastSelf(SPELL_CLEAR_ENERGY, true);
DoCastSelf(SPELL_EMBRACE_THE_LIGHT_BIND, true);
DoCastSelf(SPELL_BARRIER_OF_LIGHT, true);
events.ScheduleEvent(EVENT_EMBRACE_CHANNEL, 500ms);
}
void EndIntermission()
{
_intermission = false;
_energy = 0;
me->SetPower(POWER_ENERGY, 0);
DoCastSelf(SPELL_STOKE_THE_FLAME_REKINDLE, true);
DoCastSelf(SPELL_STOKE_THE_FLAME_REKINDLE_2, true);
ScheduleBuildEvents();
events.ScheduleEvent(EVENT_CHECK_ENERGY, 1s);
}
void SummonIntermissionAdds()
{
for (uint8 i = 0; i < 2; ++i)
{
Position pos = me->GetPosition();
pos.m_positionY += (i == 0 ? -8.0f : 8.0f);
me->SummonCreature(NPC_MELLEK_ZOMBIE_STALKER, pos, TEMPSUMMON_TIMED_DESPAWN, 35s);
}
for (uint8 i = 0; i < 3; ++i)
{
Position pos = me->GetRandomNearPosition(12.0f);
me->SummonCreature(NPC_ARATHI_NEOPHYTE, pos, TEMPSUMMON_TIMED_DESPAWN, 35s);
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
void ExecuteEvent(uint32 eventId) override
{
switch (eventId)
{
case EVENT_SACRED_FLAME:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f))
DoCast(target, SPELL_THE_SACRED_FLAME);
events.Repeat(30s);
break;
case EVENT_HOLY_FLAME:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f))
DoCast(target, SPELL_HOLY_FLAME);
events.Repeat(20s);
break;
case EVENT_HOLY_SMITE:
DoCastVictim(SPELL_HOLY_SMITE);
events.Repeat(8s);
events.Repeat(4s);
break;
case EVENT_PURIFY:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
DoCast(target, SPELL_PURIFY);
events.Repeat(25s);
break;
case EVENT_HOLY_FLAME:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
DoCast(target, SPELL_HOLY_FLAME);
events.Repeat(15s);
break;
case EVENT_INNER_FIRE:
DoCastSelf(SPELL_INNER_FIRE);
events.Repeat(45s);
events.Repeat(25s);
break;
case EVENT_BLINDING_LIGHT:
DoCastAOE(SPELL_BLINDING_LIGHT);
events.Repeat(35s);
case EVENT_SANCTIFIED_GROUND:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
me->CastSpell(target->GetPosition(), SPELL_SANCTIFIED_GROUND, true);
events.Repeat(30s);
break;
case EVENT_EMBRACE_THE_LIGHT:
DoCastAOE(SPELL_EMBRACE_THE_LIGHT);
case EVENT_CHECK_ENERGY:
if (!_intermission)
{
_energy += 2;
me->SetPower(POWER_ENERGY, std::min<uint32>(_energy, 100));
if (_energy >= 100)
StartIntermission();
}
events.Repeat(1s);
break;
case EVENT_SUMMON_NEOPHYTES:
for (uint8 i = 0; i < 3; ++i)
if (TempSummon* neophyte = me->SummonCreature(NPC_ARATHI_NEOPHYTE, me->GetRandomNearPosition(10.0f)))
neophyte->CastSpell(neophyte, SPELL_OVERWHELMING_POWER);
case EVENT_INTERMISSION_START:
StartIntermission();
break;
case EVENT_EMBRACE_CHANNEL:
DoCastSelf(SPELL_EMBRACE_THE_LIGHT);
SummonIntermissionAdds();
events.ScheduleEvent(EVENT_INTERMISSION_END, 28s);
break;
case EVENT_INTERMISSION_END:
if (me->HasUnitState(UNIT_STATE_CASTING))
events.Repeat(1s);
else
EndIntermission();
break;
default:
break;
}
}
}
private:
bool _barrierPhase;
uint32 _energy;
bool _intermission;
};
void AddSC_boss_prioress_murrpray()
@@ -33,9 +33,17 @@ static constexpr ObjectData creatureData[] =
{ 0, 0 } // END
};
static constexpr ObjectData gameObjectData[] =
{
{ GO_PRIORY_DOOR, DATA_DAILCRY_DOOR },
{ GO_PRIORY_DOOR_02, DATA_BARON_DOOR },
{ GO_FIRE_BARRIER, DATA_MURRPRAY_DOOR },
{ 0, 0 } // END
};
static constexpr DungeonEncounterData const encounters[] =
{
{ BOSS_CAPTAIN_DAILCRY, {{ 2847 }} },
{ DATA_CAPTAIN_DAILCRY, {{ 2847 }} },
{ DATA_BARON_BRAUNPYKE, {{ 2835 }} },
{ DATA_PRIORESS_MURRPRAY, {{ 2848 }} },
};
@@ -51,7 +59,7 @@ public:
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
// LoadObjectData(creatureData, nullptr);
LoadObjectData(creatureData, gameObjectData);
LoadDungeonEncounterData(encounters);
}
@@ -70,6 +78,33 @@ public:
player->GetGroup()->DespawnFollowerModeBots(player);
}
bool SetBossState(uint32 id, EncounterState state) override
{
if (state == DONE)
{
switch (id)
{
case DATA_CAPTAIN_DAILCRY:
OpenDoor(DATA_DAILCRY_DOOR);
break;
case DATA_BARON_BRAUNPYKE:
OpenDoor(DATA_BARON_DOOR);
OpenDoor(DATA_MURRPRAY_DOOR);
break;
default:
break;
}
}
return InstanceScript::SetBossState(id, state);
}
void OpenDoor(uint32 data)
{
if (GameObject* door = GetGameObject(data))
door->SetGoState(GO_STATE_ACTIVE);
}
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
@@ -19,15 +19,46 @@ enum priorityofthesacredflameDataTypes
DATA_CAPTAIN_DAILCRY = 0,
DATA_BARON_BRAUNPYKE,
DATA_PRIORESS_MURRPRAY,
// GameObjects
DATA_DAILCRY_DOOR,
DATA_BARON_DOOR,
DATA_MURRPRAY_DOOR,
};
enum priorityofthesacredflameCreatureIds
{
// Bosses
BOSS_CAPTAIN_DAILCRY = 207946,
BOSS_BARON_BRAUNPYKE = 207939,
BOSS_BARON_BRAUNPYKE = 207939, // rides a mount (Vehicle)
BOSS_PRIORESS_MURRPRAY = 207940,
// Trash
NPC_FERVENT_SHARPSHOOTER = 206694,
NPC_ARATHI_KNIGHT = 206696,
NPC_DEVOUT_PRIEST = 206697,
NPC_FANATICAL_CONJUROR = 206698,
NPC_WAR_LYNX = 206699,
NPC_ARDENT_PALADIN = 206704,
NPC_ARATHI_FOOTMAN = 206705,
NPC_LIGHTSPAWN = 206710,
NPC_ZEALOUS_TEMPLAR = 207949,
NPC_RISEN_FOOTMAN = 212835,
NPC_RISEN_MAGE = 221760,
NPC_ETERNAL_FLAME = 210851,
// Encounter support
NPC_ARATHI_NEOPHYTE = 211140,
NPC_MELLEK_ZOMBIE_STALKER = 211138,
};
enum priorityofthesacredflameGameObjectIds
{
GO_PRIORY_DOOR = 441670,
GO_PRIORY_DOOR_02 = 441671,
GO_NAVIGATION_DOOR = 441668,
GO_NAVIGATION_DOOR_02 = 441669,
GO_FIRE_BARRIER = 452050,
};
template <class AI, class T>
@@ -0,0 +1,263 @@
/*
* Copyright (C) WowCommunity Project
*
* This SourceCode is NOT free a software. Please hold everything Private
* and read our Terms
*/
#include "priority_of_the_sacred_flame.h"
#include "Containers.h"
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "TemporarySummon.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
#include "TaskScheduler.h"
#include <unordered_map>
#include <vector>
enum TrashSpells
{
// Fervent Sharpshooter (206694)
SPELL_SHOOT = 427629,
SPELL_POT_SHOT = 462859,
SPELL_CALTROPS = 453458,
// Arathi Knight (206696)
SPELL_IMPALE = 427621,
SPELL_DISRUPTING_SHOUT = 427609,
// Devout Priest (206697)
SPELL_HOLY_SMITE = 427357,
SPELL_GREATER_HEAL = 427356,
SPELL_INNER_FIRE_PRIEST = 428916,
// Fanatical Conjuror (206698)
SPELL_FIREBALL = 427469,
SPELL_FLAMESTRIKE = 427478,
// War Lynx (206699)
SPELL_POUNCE = 446776,
SPELL_GRIEVOUS_RIP = 446779,
// Ardent Paladin (206704)
SPELL_CONSECRATION = 424429,
SPELL_SACRED_TOLL = 448791,
// Arathi Footman (206705)
SPELL_DEFEND = 427342,
SPELL_SHATTERED_DEFENSES = 427360,
// Lightspawn (206710)
SPELL_PURIFICATION = 448787,
SPELL_BURST_OF_LIGHT = 427601,
// Zealous Templar (207949)
SPELL_SEAL_OF_LIGHTS_FURY = 427596,
SPELL_TEMPLARS_WRATH = 444728,
// Risen Footman (212835) / Risen Mage (221760)
SPELL_LIGHT_EXPULSION = 435156,
// Eternal Flame (210851)
SPELL_THE_SACRED_FLAME = 425544,
// Prioress Murrpray encounter support
SPELL_SUMMON_LIGHT_ZOMBIE = 425021,
SPELL_FIXATE = 425020,
SPELL_OVERWHELMING_POWER = 425022,
};
enum TrashEvents
{
EVENT_TRASH_SPELL_1 = 1,
EVENT_TRASH_SPELL_2,
EVENT_TRASH_SPELL_3,
EVENT_SUMMON_LIGHT_ZOMBIE = 101,
EVENT_FIXATE,
EVENT_OVERWHELMING_POWER,
};
enum class TrashTarget : uint8
{
Victim,
Random,
Self,
};
struct TrashSpell
{
uint32 spellId;
Milliseconds initial;
Milliseconds cooldown;
TrashTarget target;
};
static std::unordered_map<uint32, std::vector<TrashSpell>> const& GetTrashSpellTable()
{
static std::unordered_map<uint32, std::vector<TrashSpell>> const table =
{
{ NPC_FERVENT_SHARPSHOOTER, { { SPELL_SHOOT, 1s, 2s, TrashTarget::Victim }, { SPELL_POT_SHOT, 4s, 8s, TrashTarget::Random }, { SPELL_CALTROPS, 7s, 12s, TrashTarget::Random } } },
{ NPC_ARATHI_KNIGHT, { { SPELL_IMPALE, 2s, 5s, TrashTarget::Victim }, { SPELL_DISRUPTING_SHOUT, 8s, 14s, TrashTarget::Random } } },
{ NPC_DEVOUT_PRIEST, { { SPELL_HOLY_SMITE, 2s, 3s, TrashTarget::Victim }, { SPELL_GREATER_HEAL, 10s, 15s, TrashTarget::Self }, { SPELL_INNER_FIRE_PRIEST, 5s, 20s, TrashTarget::Self } } },
{ NPC_FANATICAL_CONJUROR, { { SPELL_FIREBALL, 2s, 3s, TrashTarget::Victim }, { SPELL_FLAMESTRIKE, 8s, 14s, TrashTarget::Random } } },
{ NPC_WAR_LYNX, { { SPELL_POUNCE, 3s, 8s, TrashTarget::Victim }, { SPELL_GRIEVOUS_RIP, 5s, 6s, TrashTarget::Victim } } },
{ NPC_ARDENT_PALADIN, { { SPELL_CONSECRATION, 4s, 12s, TrashTarget::Self }, { SPELL_SACRED_TOLL, 6s, 8s, TrashTarget::Victim } } },
{ NPC_ARATHI_FOOTMAN, { { SPELL_DEFEND, 3s, 16s, TrashTarget::Self }, { SPELL_SHATTERED_DEFENSES, 6s, 10s, TrashTarget::Victim } } },
{ NPC_LIGHTSPAWN, { { SPELL_PURIFICATION, 3s, 9s, TrashTarget::Victim }, { SPELL_BURST_OF_LIGHT, 8s, 15s, TrashTarget::Self } } },
{ NPC_ZEALOUS_TEMPLAR, { { SPELL_SEAL_OF_LIGHTS_FURY, 2s, 5s, TrashTarget::Victim }, { SPELL_TEMPLARS_WRATH, 7s, 12s, TrashTarget::Victim } } },
{ NPC_RISEN_FOOTMAN, { { SPELL_LIGHT_EXPULSION, 3s, 8s, TrashTarget::Random } } },
{ NPC_RISEN_MAGE, { { SPELL_FIREBALL, 2s, 3s, TrashTarget::Victim }, { SPELL_LIGHT_EXPULSION, 8s, 12s, TrashTarget::Random } } },
{ NPC_ETERNAL_FLAME, { { SPELL_THE_SACRED_FLAME, 3s, 8s, TrashTarget::Random } } },
};
return table;
}
// Shared AI used by generic Priory of the Sacred Flame trash mobs.
struct posf_trash_ai : public ScriptedAI
{
posf_trash_ai(Creature* creature) : ScriptedAI(creature) { }
void Reset() override
{
events.Reset();
_active.clear();
auto const& table = GetTrashSpellTable();
auto it = table.find(me->GetEntry());
if (it == table.end())
return;
uint32 eventId = EVENT_TRASH_SPELL_1;
for (TrashSpell const& spell : it->second)
{
_active[eventId] = spell;
events.ScheduleEvent(eventId, spell.initial);
++eventId;
}
}
void ExecuteEvent(uint32 eventId) override
{
auto it = _active.find(eventId);
if (it == _active.end())
return;
TrashSpell const& spell = it->second;
switch (spell.target)
{
case TrashTarget::Victim:
DoCastVictim(spell.spellId);
break;
case TrashTarget::Random:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
DoCast(target, spell.spellId);
break;
case TrashTarget::Self:
DoCastSelf(spell.spellId);
break;
}
events.Repeat(spell.cooldown);
}
private:
std::unordered_map<uint32, TrashSpell> _active;
};
// 211138 - Mellek Zombie Stalker: stationary summoner used during the intermission.
struct npc_mellek_zombie_stalker : public ScriptedAI
{
npc_mellek_zombie_stalker(Creature* creature) : ScriptedAI(creature), _summons(0) { }
void Reset() override
{
_summons = 0;
_summonTimer = 1s;
}
void UpdateAI(uint32 diff) override
{
if (_summons >= 4)
return;
if (_summonTimer <= Milliseconds(diff))
{
DoCastSelf(SPELL_SUMMON_LIGHT_ZOMBIE);
++_summons;
_summonTimer = 4s;
}
else
_summonTimer -= Milliseconds(diff);
}
private:
uint8 _summons;
Milliseconds _summonTimer;
};
// 211140 - Arathi Neophyte: fixates a player and pulses Overwhelming Power.
struct npc_arathi_neophyte : public ScriptedAI
{
npc_arathi_neophyte(Creature* creature) : ScriptedAI(creature) { }
void JustEngagedWith(Unit* /*who*/) override
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
DoCast(target, SPELL_FIXATE);
events.ScheduleEvent(EVENT_OVERWHELMING_POWER, 6s);
}
void ExecuteEvent(uint32 eventId) override
{
switch (eventId)
{
case EVENT_FIXATE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
DoCast(target, SPELL_FIXATE);
break;
case EVENT_OVERWHELMING_POWER:
DoCastSelf(SPELL_OVERWHELMING_POWER);
events.Repeat(8s);
break;
default:
break;
}
}
};
struct npc_fervent_sharpshooter : public posf_trash_ai { npc_fervent_sharpshooter(Creature* c) : posf_trash_ai(c) { } };
struct npc_arathi_knight : public posf_trash_ai { npc_arathi_knight(Creature* c) : posf_trash_ai(c) { } };
struct npc_devout_priest : public posf_trash_ai { npc_devout_priest(Creature* c) : posf_trash_ai(c) { } };
struct npc_fanatical_conjuror : public posf_trash_ai { npc_fanatical_conjuror(Creature* c) : posf_trash_ai(c) { } };
struct npc_war_lynx : public posf_trash_ai { npc_war_lynx(Creature* c) : posf_trash_ai(c) { } };
struct npc_ardent_paladin : public posf_trash_ai { npc_ardent_paladin(Creature* c) : posf_trash_ai(c) { } };
struct npc_arathi_footman : public posf_trash_ai { npc_arathi_footman(Creature* c) : posf_trash_ai(c) { } };
struct npc_lightspawn : public posf_trash_ai { npc_lightspawn(Creature* c) : posf_trash_ai(c) { } };
struct npc_zealous_templar : public posf_trash_ai { npc_zealous_templar(Creature* c) : posf_trash_ai(c) { } };
struct npc_risen_footman : public posf_trash_ai { npc_risen_footman(Creature* c) : posf_trash_ai(c) { } };
struct npc_risen_mage : public posf_trash_ai { npc_risen_mage(Creature* c) : posf_trash_ai(c) { } };
struct npc_eternal_flame : public posf_trash_ai { npc_eternal_flame(Creature* c) : posf_trash_ai(c) { } };
void AddSC_priority_of_the_sacred_flame()
{
RegisterPriorityoftheSacredflameCreatureAI(npc_fervent_sharpshooter);
RegisterPriorityoftheSacredflameCreatureAI(npc_arathi_knight);
RegisterPriorityoftheSacredflameCreatureAI(npc_devout_priest);
RegisterPriorityoftheSacredflameCreatureAI(npc_fanatical_conjuror);
RegisterPriorityoftheSacredflameCreatureAI(npc_war_lynx);
RegisterPriorityoftheSacredflameCreatureAI(npc_ardent_paladin);
RegisterPriorityoftheSacredflameCreatureAI(npc_arathi_footman);
RegisterPriorityoftheSacredflameCreatureAI(npc_lightspawn);
RegisterPriorityoftheSacredflameCreatureAI(npc_zealous_templar);
RegisterPriorityoftheSacredflameCreatureAI(npc_risen_footman);
RegisterPriorityoftheSacredflameCreatureAI(npc_risen_mage);
RegisterPriorityoftheSacredflameCreatureAI(npc_eternal_flame);
RegisterPriorityoftheSacredflameCreatureAI(npc_mellek_zombie_stalker);
RegisterPriorityoftheSacredflameCreatureAI(npc_arathi_neophyte);
}
@@ -22,6 +22,7 @@ void AddSC_instance_priority_of_the_sacred_flame();
void AddSC_boss_baron_braunpyke();
void AddSC_boss_captain_dailcry();
void AddSC_boss_prioress_murrpray();
void AddSC_priority_of_the_sacred_flame();
// The name of this function should match:
// void Add${NameOfDirectory}Scripts()
@@ -40,5 +41,6 @@ void AddWarWithinScripts()
AddSC_boss_baron_braunpyke();
AddSC_boss_captain_dailcry();
AddSC_boss_prioress_murrpray();
AddSC_priority_of_the_sacred_flame();
}