Scripts/Halls of Origination: modernized scripting models to current standard

* dropped a deprecated hack spellscript from Anraphet
This commit is contained in:
Ovahlord
2023-12-25 17:16:03 +01:00
parent 75300c90b6
commit 5c6040feba
5 changed files with 675 additions and 844 deletions

View File

@@ -0,0 +1 @@
DELETE FROM `spell_script_names` WHERE `ScriptName`= 'spell_anraphet_omega_stance_spider_effect';

View File

@@ -132,442 +132,347 @@ Position const BrannIntroWaypoint[MAX_BRANN_WAYPOINTS_INTRO] =
{-35.04861f, 366.6563f, 89.77447f, 0.0f},
};
class boss_anraphet : public CreatureScript
struct boss_anraphet : public BossAI
{
public:
boss_anraphet() : CreatureScript("boss_anraphet") { }
boss_anraphet(Creature* creature) : BossAI(creature, BOSS_ANRAPHET) { }
struct boss_anraphetAI : public BossAI
void ScheduleCombatEvents()
{
boss_anraphetAI(Creature* creature) : BossAI(creature, BOSS_ANRAPHET) { }
events.ScheduleEvent(EVENT_ANRAPHET_NEMESIS_STRIKE, 8s, 0, PHASE_COMBAT);
events.ScheduleEvent(EVENT_ANRAPHET_ALPHA_BEAMS, 10s, 0, PHASE_COMBAT);
events.ScheduleEvent(EVENT_ANRAPHET_OMEGA_STANCE, 35s, 0, PHASE_COMBAT);
}
void ScheduleCombatEvents()
{
events.ScheduleEvent(EVENT_ANRAPHET_NEMESIS_STRIKE, 8s, 0, PHASE_COMBAT);
events.ScheduleEvent(EVENT_ANRAPHET_ALPHA_BEAMS, 10s, 0, PHASE_COMBAT);
events.ScheduleEvent(EVENT_ANRAPHET_OMEGA_STANCE, 35s, 0, PHASE_COMBAT);
}
void Reset() override
{
_Reset();
me->SetWalk(false);
events.SetPhase(PHASE_INTRO);
if (instance->GetData(DATA_DEAD_ELEMENTALS) == 4)
{
// Set to combat automatically, Brann's event won't repeat
me->SetUninteractible(false);
events.SetPhase(PHASE_COMBAT);
ScheduleCombatEvents();
me->SetHomePosition(AnraphetActivatePos);
}
}
void JustEngagedWith(Unit* who) override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
Talk(ANRAPHET_SAY_AGGRO);
BossAI::JustEngagedWith(who);
}
void JustDied(Unit* /*killer*/) override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
Talk(ANRAPHET_SAY_DEATH);
if (Creature* brann = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BRANN_0_GUID)))
brann->AI()->DoAction(ACTION_ANRAPHET_DIED);
_JustDied();
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(ANRAPHET_SAY_KILL);
}
void JustReachedHome() override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_JustReachedHome();
instance->SetBossState(BOSS_ANRAPHET, FAIL);
}
void DoAction(int32 action) override
{
if (action == ACTION_ANRAPHET_INTRO)
events.ScheduleEvent(EVENT_ANRAPHET_APPEAR, 6s, 0, PHASE_INTRO);
}
void MovementInform(uint32 type, uint32 point) override
{
if (type != POINT_MOTION_TYPE)
return;
if (point == POINT_ANRAPHET_ACTIVATE)
{
events.ScheduleEvent(EVENT_ANRAPHET_ACTIVATE, 1500ms, 0, PHASE_INTRO);
me->SetHomePosition(AnraphetActivatePos);
}
}
void UpdateAI(uint32 diff) override
{
if ((events.GetPhaseMask() & PHASE_MASK_COMBAT) && (!UpdateVictim() || !CheckInRoom()))
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_ANRAPHET_APPEAR:
me->SetWalk(true);
me->GetMotionMaster()->MovePoint(POINT_ANRAPHET_ACTIVATE, AnraphetActivatePos);
break;
case EVENT_ANRAPHET_ACTIVATE:
me->SetWalk(false);
Talk(ANRAPHET_SAY_INTRO);
events.ScheduleEvent(EVENT_ANRAPHET_DESTROY, 17500ms, 0, PHASE_INTRO);
return;
case EVENT_ANRAPHET_DESTROY:
DoCastAOE(SPELL_DESTRUCTION_PROTOCOL);
events.ScheduleEvent(EVENT_ANRAPHET_READY, 6s, 0, PHASE_INTRO);
break;
case EVENT_ANRAPHET_READY:
me->SetUninteractible(false);
events.SetPhase(PHASE_COMBAT);
ScheduleCombatEvents();
break;
case EVENT_ANRAPHET_NEMESIS_STRIKE:
DoCastVictim(SPELL_NEMESIS_STRIKE);
events.ScheduleEvent(EVENT_ANRAPHET_NEMESIS_STRIKE, 21500ms, 0, PHASE_COMBAT);
break;
case EVENT_ANRAPHET_ALPHA_BEAMS:
DoCast(me, SPELL_ALPHA_BEAMS);
events.ScheduleEvent(EVENT_ANRAPHET_CRUMBLING_RUIN, 12500ms, 0, PHASE_COMBAT);
events.ScheduleEvent(EVENT_ANRAPHET_ALPHA_BEAMS, 40s, 45s, 0, PHASE_COMBAT);
break;
case EVENT_ANRAPHET_OMEGA_STANCE:
DoCast(me, SPELL_OMEGA_STANCE_SUMMON);
DoCast(me, SPELL_OMEGA_STANCE);
Talk(ANRAPHET_SAY_OMEGA_STANCE);
events.ScheduleEvent(EVENT_ANRAPHET_OMEGA_STANCE, 45s, 50s, 0, PHASE_COMBAT);
events.ScheduleEvent(EVENT_ANRAPHET_CRUMBLING_RUIN, 13s, 0, PHASE_COMBAT);
break;
case EVENT_ANRAPHET_CRUMBLING_RUIN:
DoCast(me, SPELL_CRUMBLING_RUIN);
break;
}
}
if (events.GetPhaseMask() & PHASE_MASK_COMBAT)
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
void Reset() override
{
return GetHallsOfOriginationAI<boss_anraphetAI>(creature);
_Reset();
me->SetWalk(false);
events.SetPhase(PHASE_INTRO);
if (instance->GetData(DATA_DEAD_ELEMENTALS) == 4)
{
// Set to combat automatically, Brann's event won't repeat
me->SetUninteractible(false);
events.SetPhase(PHASE_COMBAT);
ScheduleCombatEvents();
me->SetHomePosition(AnraphetActivatePos);
}
}
void JustEngagedWith(Unit* who) override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
Talk(ANRAPHET_SAY_AGGRO);
BossAI::JustEngagedWith(who);
}
void JustDied(Unit* /*killer*/) override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
Talk(ANRAPHET_SAY_DEATH);
if (Creature* brann = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BRANN_0_GUID)))
brann->AI()->DoAction(ACTION_ANRAPHET_DIED);
_JustDied();
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(ANRAPHET_SAY_KILL);
}
void JustReachedHome() override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_JustReachedHome();
instance->SetBossState(BOSS_ANRAPHET, FAIL);
}
void DoAction(int32 action) override
{
if (action == ACTION_ANRAPHET_INTRO)
events.ScheduleEvent(EVENT_ANRAPHET_APPEAR, 6s, 0, PHASE_INTRO);
}
void MovementInform(uint32 type, uint32 point) override
{
if (type != POINT_MOTION_TYPE)
return;
if (point == POINT_ANRAPHET_ACTIVATE)
{
events.ScheduleEvent(EVENT_ANRAPHET_ACTIVATE, 1500ms, 0, PHASE_INTRO);
me->SetHomePosition(AnraphetActivatePos);
}
}
void UpdateAI(uint32 diff) override
{
if ((events.GetPhaseMask() & PHASE_MASK_COMBAT) && (!UpdateVictim() || !CheckInRoom()))
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_ANRAPHET_APPEAR:
me->SetWalk(true);
me->GetMotionMaster()->MovePoint(POINT_ANRAPHET_ACTIVATE, AnraphetActivatePos);
break;
case EVENT_ANRAPHET_ACTIVATE:
me->SetWalk(false);
Talk(ANRAPHET_SAY_INTRO);
events.ScheduleEvent(EVENT_ANRAPHET_DESTROY, 17500ms, 0, PHASE_INTRO);
return;
case EVENT_ANRAPHET_DESTROY:
DoCastAOE(SPELL_DESTRUCTION_PROTOCOL);
events.ScheduleEvent(EVENT_ANRAPHET_READY, 6s, 0, PHASE_INTRO);
break;
case EVENT_ANRAPHET_READY:
me->SetUninteractible(false);
events.SetPhase(PHASE_COMBAT);
ScheduleCombatEvents();
break;
case EVENT_ANRAPHET_NEMESIS_STRIKE:
DoCastVictim(SPELL_NEMESIS_STRIKE);
events.ScheduleEvent(EVENT_ANRAPHET_NEMESIS_STRIKE, 21500ms, 0, PHASE_COMBAT);
break;
case EVENT_ANRAPHET_ALPHA_BEAMS:
DoCast(me, SPELL_ALPHA_BEAMS);
events.ScheduleEvent(EVENT_ANRAPHET_CRUMBLING_RUIN, 12500ms, 0, PHASE_COMBAT);
events.ScheduleEvent(EVENT_ANRAPHET_ALPHA_BEAMS, 40s, 45s, 0, PHASE_COMBAT);
break;
case EVENT_ANRAPHET_OMEGA_STANCE:
DoCast(me, SPELL_OMEGA_STANCE_SUMMON);
DoCast(me, SPELL_OMEGA_STANCE);
Talk(ANRAPHET_SAY_OMEGA_STANCE);
events.ScheduleEvent(EVENT_ANRAPHET_OMEGA_STANCE, 45s, 50s, 0, PHASE_COMBAT);
events.ScheduleEvent(EVENT_ANRAPHET_CRUMBLING_RUIN, 13s, 0, PHASE_COMBAT);
break;
case EVENT_ANRAPHET_CRUMBLING_RUIN:
DoCast(me, SPELL_CRUMBLING_RUIN);
break;
}
}
if (events.GetPhaseMask() & PHASE_MASK_COMBAT)
DoMeleeAttackIfReady();
}
};
class npc_omega_stance : public CreatureScript
struct npc_omega_stance : public ScriptedAI
{
public:
npc_omega_stance() : CreatureScript("npc_omega_stance") { }
npc_omega_stance(Creature* creature) : ScriptedAI(creature) { }
struct npc_omega_stanceAI : public ScriptedAI
{
npc_omega_stanceAI(Creature* creature) : ScriptedAI(creature) { }
void IsSummonedBy(WorldObject* /*who*/) override
{
DoCast(me, SPELL_OMEGA_STANCE_SPIDER_TRIGGER, true);
}
void IsSummonedBy(WorldObject* /*who*/) override
{
DoCast(me, SPELL_OMEGA_STANCE_SPIDER_TRIGGER, true);
}
void EnterEvadeMode(EvadeReason /*why*/) override { }
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetHallsOfOriginationAI<npc_omega_stanceAI>(creature);
}
void EnterEvadeMode(EvadeReason /*why*/) override { }
};
class npc_alpha_beam : public CreatureScript
struct npc_alpha_beam : public ScriptedAI
{
public:
npc_alpha_beam() : CreatureScript("npc_alpha_beam") { }
npc_alpha_beam(Creature* creature) : ScriptedAI(creature), _instance(nullptr) { }
struct npc_alpha_beamAI : public ScriptedAI
void InitializeAI() override
{
_instance = me->GetInstanceScript();
}
void IsSummonedBy(WorldObject* /*summoner*/) override
{
if (Creature* anraphet = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_ANRAPHET_GUID)))
anraphet->CastSpell(me, SPELL_ALPHA_BEAMS_BACK_CAST);
}
void EnterEvadeMode(EvadeReason /*why*/) override { } // Never evade
private:
InstanceScript* _instance;
};
struct npc_brann_bronzebeard_anraphet : public CreatureAI
{
npc_brann_bronzebeard_anraphet(Creature* creature) : CreatureAI(creature), _currentPoint(0), _instance(nullptr) { }
void InitializeAI() override
{
_instance = me->GetInstanceScript();
}
bool OnGossipSelect(Player* /*player*/, uint32 menuId, uint32 action) override
{
if (_instance->GetBossState(BOSS_VAULT_OF_LIGHTS) == DONE)
return true;
if (menuId == GOSSIP_MENU_START_INTRO && !action)
{
npc_alpha_beamAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
_instance->SetBossState(BOSS_VAULT_OF_LIGHTS, IN_PROGRESS);
_currentPoint = 0;
events.Reset();
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
me->SetWalk(true);
Talk(BRANN_SAY_DOOR_INTRO);
events.ScheduleEvent(EVENT_BRANN_UNLOCK_DOOR, 7500ms);
}
return false;
}
void IsSummonedBy(WorldObject* /*summoner*/) override
void DoAction(int32 action) override
{
switch (action)
{
case ACTION_ELEMENTAL_DIED:
{
uint32 dead = _instance->GetData(DATA_DEAD_ELEMENTALS);
Talk(BRANN_1_ELEMENTAL_DEAD + dead - 1);
if (dead == 4)
{
_instance->DoCastSpellOnPlayers(SPELL_VAULT_OF_LIGHTS_CREDIT);
if (Creature* anraphet = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_ANRAPHET_GUID)))
anraphet->CastSpell(me, SPELL_ALPHA_BEAMS_BACK_CAST);
anraphet->AI()->DoAction(ACTION_ANRAPHET_INTRO);
}
void EnterEvadeMode(EvadeReason /*why*/) override { } // Never evade
private:
InstanceScript* _instance;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetHallsOfOriginationAI<npc_alpha_beamAI>(creature);
break;
}
};
class npc_brann_bronzebeard_anraphet : public CreatureScript
{
public:
npc_brann_bronzebeard_anraphet() : CreatureScript("npc_brann_bronzebeard_anraphet") { }
struct npc_brann_bronzebeard_anraphetAI : public CreatureAI
{
npc_brann_bronzebeard_anraphetAI(Creature* creature) : CreatureAI(creature), _currentPoint(0), _instance(creature->GetInstanceScript()) { }
bool OnGossipSelect(Player* /*player*/, uint32 menuId, uint32 action) override
{
if (_instance->GetBossState(BOSS_VAULT_OF_LIGHTS) == DONE)
return true;
if (menuId == GOSSIP_MENU_START_INTRO && !action)
{
_instance->SetBossState(BOSS_VAULT_OF_LIGHTS, IN_PROGRESS);
_currentPoint = 0;
events.Reset();
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
me->SetWalk(true);
Talk(BRANN_SAY_DOOR_INTRO);
events.ScheduleEvent(EVENT_BRANN_UNLOCK_DOOR, 7500ms);
}
return false;
}
void DoAction(int32 action) override
{
switch (action)
{
case ACTION_ELEMENTAL_DIED:
{
uint32 dead = _instance->GetData(DATA_DEAD_ELEMENTALS);
Talk(BRANN_1_ELEMENTAL_DEAD + dead - 1);
if (dead == 4)
{
_instance->DoCastSpellOnPlayers(SPELL_VAULT_OF_LIGHTS_CREDIT);
if (Creature* anraphet = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_ANRAPHET_GUID)))
anraphet->AI()->DoAction(ACTION_ANRAPHET_INTRO);
}
break;
}
case ACTION_ANRAPHET_DIED:
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, 1s);
break;
}
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_BRANN_MOVE_INTRO:
if (_currentPoint < MAX_BRANN_WAYPOINTS_INTRO)
me->GetMotionMaster()->MovePoint(_currentPoint, BrannIntroWaypoint[_currentPoint]);
break;
case EVENT_BRANN_UNLOCK_DOOR:
Talk(BRANN_SAY_UNLOCK_DOOR);
_instance->SetBossState(BOSS_VAULT_OF_LIGHTS, DONE);
_instance->TriggerGameEvent(ACHIEV_VAULT_OF_LIGHTS_EVENT);
events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, 3500ms);
break;
case EVENT_BRANN_THINK:
Talk(BRANN_SAY_THINK);
events.ScheduleEvent(EVENT_BRANN_SET_ORIENTATION_1, 6s);
break;
case EVENT_BRANN_SET_ORIENTATION_1:
me->SetFacingTo(5.445427f);
Talk(BRANN_SAY_MIRRORS);
events.ScheduleEvent(EVENT_BRANN_SET_ORIENTATION_2, 1s);
break;
case EVENT_BRANN_SET_ORIENTATION_2:
me->SetFacingTo(0.6283185f);
events.ScheduleEvent(EVENT_BRANN_SET_ORIENTATION_3, 2500ms);
break;
case EVENT_BRANN_SET_ORIENTATION_3:
me->SetFacingTo(0.01745329f);
events.ScheduleEvent(EVENT_BRANN_SAY_ELEMENTALS, 200ms);
break;
case EVENT_BRANN_SAY_ELEMENTALS:
Talk(BRANN_SAY_ELEMENTALS);
events.ScheduleEvent(EVENT_BRANN_SAY_GET_IT, 3500ms);
break;
case EVENT_BRANN_SAY_GET_IT:
Talk(BRANN_SAY_GET_IT);
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
break;
case EVENT_BRANN_SET_ORIENTATION_4:
me->SetFacingTo(3.141593f);
break;
}
}
}
void MovementInform(uint32 movementType, uint32 pointId) override
{
if (movementType != POINT_MOTION_TYPE)
return;
_currentPoint = pointId + 1;
Milliseconds delay = 1ms;
switch (pointId)
{
case 0:
Talk(BRANN_SAY_TROGGS);
events.ScheduleEvent(EVENT_BRANN_THINK, 15s);
return;
case 1:
Talk(BRANN_SAY_ANRAPHET_DIED);
delay = 1s;
break;
case 14:
Talk(BRANN_SAY_MOMENT);
delay = 2200ms;
break;
case 16:
events.ScheduleEvent(EVENT_BRANN_SET_ORIENTATION_4, 6s);
return;
default:
break;
}
events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, delay);
}
protected:
EventMap events;
uint32 _currentPoint;
InstanceScript* _instance;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetHallsOfOriginationAI<npc_brann_bronzebeard_anraphetAI>(creature);
case ACTION_ANRAPHET_DIED:
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, 1s);
break;
}
};
}
class spell_anraphet_alpha_beams : public SpellScriptLoader
{
public:
spell_anraphet_alpha_beams() : SpellScriptLoader("spell_anraphet_alpha_beams") { }
class spell_anraphet_alpha_beams_SpellScript : public SpellScript
void UpdateAI(uint32 diff) override
{
void FilterTargets(std::list<WorldObject*>& targets)
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
if (targets.empty())
switch (eventId)
{
case EVENT_BRANN_MOVE_INTRO:
if (_currentPoint < MAX_BRANN_WAYPOINTS_INTRO)
me->GetMotionMaster()->MovePoint(_currentPoint, BrannIntroWaypoint[_currentPoint]);
break;
case EVENT_BRANN_UNLOCK_DOOR:
Talk(BRANN_SAY_UNLOCK_DOOR);
_instance->SetBossState(BOSS_VAULT_OF_LIGHTS, DONE);
_instance->TriggerGameEvent(ACHIEV_VAULT_OF_LIGHTS_EVENT);
events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, 3500ms);
break;
case EVENT_BRANN_THINK:
Talk(BRANN_SAY_THINK);
events.ScheduleEvent(EVENT_BRANN_SET_ORIENTATION_1, 6s);
break;
case EVENT_BRANN_SET_ORIENTATION_1:
me->SetFacingTo(5.445427f);
Talk(BRANN_SAY_MIRRORS);
events.ScheduleEvent(EVENT_BRANN_SET_ORIENTATION_2, 1s);
break;
case EVENT_BRANN_SET_ORIENTATION_2:
me->SetFacingTo(0.6283185f);
events.ScheduleEvent(EVENT_BRANN_SET_ORIENTATION_3, 2500ms);
break;
case EVENT_BRANN_SET_ORIENTATION_3:
me->SetFacingTo(0.01745329f);
events.ScheduleEvent(EVENT_BRANN_SAY_ELEMENTALS, 200ms);
break;
case EVENT_BRANN_SAY_ELEMENTALS:
Talk(BRANN_SAY_ELEMENTALS);
events.ScheduleEvent(EVENT_BRANN_SAY_GET_IT, 3500ms);
break;
case EVENT_BRANN_SAY_GET_IT:
Talk(BRANN_SAY_GET_IT);
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
break;
case EVENT_BRANN_SET_ORIENTATION_4:
me->SetFacingTo(3.141593f);
break;
}
}
}
void MovementInform(uint32 movementType, uint32 pointId) override
{
if (movementType != POINT_MOTION_TYPE)
return;
_currentPoint = pointId + 1;
Milliseconds delay = 1ms;
switch (pointId)
{
case 0:
Talk(BRANN_SAY_TROGGS);
events.ScheduleEvent(EVENT_BRANN_THINK, 15s);
return;
WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
targets.clear();
targets.push_back(target);
case 1:
Talk(BRANN_SAY_ANRAPHET_DIED);
delay = 1s;
break;
case 14:
Talk(BRANN_SAY_MOMENT);
delay = 2200ms;
break;
case 16:
events.ScheduleEvent(EVENT_BRANN_SET_ORIENTATION_4, 6s);
return;
default:
break;
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_anraphet_alpha_beams_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, delay);
}
SpellScript* GetSpellScript() const override
protected:
EventMap events;
uint32 _currentPoint;
InstanceScript* _instance;
};
class spell_anraphet_alpha_beams : public SpellScript
{
void FilterTargets(std::list<WorldObject*>& targets)
{
return new spell_anraphet_alpha_beams_SpellScript();
if (targets.empty())
return;
Trinity::Containers::RandomResize(targets, 1);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_anraphet_alpha_beams::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
// 77106 - Omega Stance (Summon)
class spell_anraphet_omega_stance_summon : public SpellScriptLoader
class spell_anraphet_omega_stance_summon : public SpellScript
{
public:
spell_anraphet_omega_stance_summon() : SpellScriptLoader("spell_anraphet_omega_stance_summon") { }
class spell_anraphet_omega_stance_summon_SpellScript : public SpellScript
void SetDest(SpellDestination& dest)
{
void SetDest(SpellDestination& dest)
{
dest.RelocateOffset({ 0.0f, 0.0f, 30.0f, 0.0f });
}
void Register() override
{
OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_anraphet_omega_stance_summon_SpellScript::SetDest, EFFECT_0, TARGET_DEST_DEST);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_anraphet_omega_stance_summon_SpellScript();
dest.RelocateOffset({ 0.0f, 0.0f, 30.0f, 0.0f });
}
};
// 77127 Omega Stance Spider Effect
class spell_anraphet_omega_stance_spider_effect : public SpellScriptLoader
{
public:
spell_anraphet_omega_stance_spider_effect() : SpellScriptLoader("spell_anraphet_omega_stance_spider_effect") { }
class spell_anraphet_omega_stance_spider_effect_SpellScript : public SpellScript
void Register() override
{
void SetDest(SpellDestination& dest)
{
// Do our own calculations for the destination position.
/// TODO: Remove this once we find a general rule for WorldObject::MovePosition (this spell shouldn't take the Z change into consideration)
Unit* caster = GetCaster();
float angle = rand_norm() * static_cast<float>(2 * M_PI);
uint32 dist = caster->GetCombatReach() + GetSpellInfo()->GetEffect(EFFECT_0).CalcRadius(caster, SpellTargetIndex::TargetB) * rand_norm();
float x = caster->GetPositionX() + dist * std::cos(angle);
float y = caster->GetPositionY() + dist * std::sin(angle);
float z = caster->GetMap()->GetHeight(caster->GetPhaseShift(), x, y, caster->GetPositionZ());
float o = dest._position.GetOrientation();
dest.Relocate({ x, y, z, o });
}
void Register() override
{
OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_anraphet_omega_stance_spider_effect_SpellScript::SetDest, EFFECT_0, TARGET_DEST_CASTER_RANDOM);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_anraphet_omega_stance_spider_effect_SpellScript();
OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_anraphet_omega_stance_summon::SetDest, EFFECT_0, TARGET_DEST_DEST);
}
};
void AddSC_boss_anraphet()
{
new boss_anraphet();
new spell_anraphet_alpha_beams();
new npc_brann_bronzebeard_anraphet();
new npc_alpha_beam();
new spell_anraphet_omega_stance_summon();
new spell_anraphet_omega_stance_spider_effect();
new npc_omega_stance();
RegisterHallsOfOriginationCreatureAI(boss_anraphet);
RegisterHallsOfOriginationCreatureAI(npc_brann_bronzebeard_anraphet);
RegisterHallsOfOriginationCreatureAI(npc_alpha_beam);
RegisterHallsOfOriginationCreatureAI(npc_omega_stance);
RegisterSpellScript(spell_anraphet_alpha_beams);
RegisterSpellScript(spell_anraphet_omega_stance_summon);
}

View File

@@ -92,236 +92,203 @@ protected:
InstanceScript* _instance;
};
class boss_earthrager_ptah : public CreatureScript
struct boss_earthrager_ptah : public BossAI
{
public:
boss_earthrager_ptah() : CreatureScript("boss_earthrager_ptah") { }
boss_earthrager_ptah(Creature* creature) : BossAI(creature, BOSS_EARTHRAGER_PTAH), _summonDeaths(0), _hasDispersed(false) { }
struct boss_earthrager_ptahAI : public BossAI
void Cleanup()
{
boss_earthrager_ptahAI(Creature* creature) : BossAI(creature, BOSS_EARTHRAGER_PTAH), _summonDeaths(0), _hasDispersed(false) { }
std::list<Creature*> units;
void Cleanup()
GetCreatureListWithEntryInGrid(units, me, NPC_DUSTBONE_HORROR, 100.0f);
for (std::list<Creature*>::iterator itr = units.begin(); itr != units.end(); ++itr)
(*itr)->DespawnOrUnsummon();
units.clear();
GetCreatureListWithEntryInGrid(units, me, NPC_JEWELED_SCARAB, 100.0f);
for (std::list<Creature*>::iterator itr = units.begin(); itr != units.end(); ++itr)
(*itr)->DespawnOrUnsummon();
}
void Reset() override
{
_summonDeaths = 0;
_hasDispersed = false;
Cleanup();
_Reset();
events.SetPhase(PHASE_NORMAL);
events.ScheduleEvent(EVENT_RAGING_SMASH, 7s, 12s, 0, PHASE_NORMAL);
events.ScheduleEvent(EVENT_FLAME_BOLT, 15s, 0, PHASE_NORMAL);
events.ScheduleEvent(EVENT_EARTH_SPIKE, 16s, 21s, 0, PHASE_NORMAL);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
{
if (me->HealthBelowPctDamaged(50, damage) && (events.GetPhaseMask() & PHASE_MASK_NORMAL) && !_hasDispersed)
{
std::list<Creature*> units;
events.SetPhase(PHASE_DISPERSE);
_hasDispersed = true;
GetCreatureListWithEntryInGrid(units, me, NPC_DUSTBONE_HORROR, 100.0f);
for (std::list<Creature*>::iterator itr = units.begin(); itr != units.end(); ++itr)
(*itr)->DespawnOrUnsummon();
me->AttackStop();
DoCast(me, SPELL_SANDSTORM);
me->GetMap()->SetZoneWeather(AREA_TOMB_OF_THE_EARTHRAGER, WEATHER_STATE_LIGHT_SANDSTORM, 1.0f);
events.ScheduleEvent(EVENT_PTAH_EXPLODE, 6s, 0, PHASE_DISPERSE);
events.ScheduleEvent(EVENT_QUICKSAND, 10s, 0, PHASE_DISPERSE);
units.clear();
GetCreatureListWithEntryInGrid(units, me, NPC_JEWELED_SCARAB, 100.0f);
for (std::list<Creature*>::iterator itr = units.begin(); itr != units.end(); ++itr)
(*itr)->DespawnOrUnsummon();
}
std::list<Creature*> stalkers;
GetCreatureListWithEntryInGrid(stalkers, me, NPC_BEETLE_STALKER, 100.0f);
std::list<Creature*> beetlers = stalkers;
void Reset() override
{
_summonDeaths = 0;
_hasDispersed = false;
Cleanup();
_Reset();
events.SetPhase(PHASE_NORMAL);
events.ScheduleEvent(EVENT_RAGING_SMASH, 7s, 12s, 0, PHASE_NORMAL);
events.ScheduleEvent(EVENT_FLAME_BOLT, 15s, 0, PHASE_NORMAL);
events.ScheduleEvent(EVENT_EARTH_SPIKE, 16s, 21s, 0, PHASE_NORMAL);
}
Trinity::Containers::RandomResize(beetlers, 9); // Holds the summoners of Jeweled Scarab
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
{
if (me->HealthBelowPctDamaged(50, damage) && (events.GetPhaseMask() & PHASE_MASK_NORMAL) && !_hasDispersed)
for (std::list<Creature*>::iterator itr = beetlers.begin(); itr != beetlers.end(); ++itr)
{
events.SetPhase(PHASE_DISPERSE);
_hasDispersed = true;
stalkers.remove((*itr)); // Remove it to prevent a single trigger from spawning multiple npcs.
(*itr)->CastSpell((*itr), SPELL_BEETLE_BURROW); // Cast visual
// Summon after 5 seconds.
(*itr)->m_Events.AddEventAtOffset(new SummonScarab((*itr), instance), 5s);
}
me->AttackStop();
DoCast(me, SPELL_SANDSTORM);
me->GetMap()->SetZoneWeather(AREA_TOMB_OF_THE_EARTHRAGER, WEATHER_STATE_LIGHT_SANDSTORM, 1.0f);
events.ScheduleEvent(EVENT_PTAH_EXPLODE, 6s, 0, PHASE_DISPERSE);
events.ScheduleEvent(EVENT_QUICKSAND, 10s, 0, PHASE_DISPERSE);
Trinity::Containers::RandomResize(stalkers, 2); // Holds the summoners of Dustbone Horror
std::list<Creature*> stalkers;
GetCreatureListWithEntryInGrid(stalkers, me, NPC_BEETLE_STALKER, 100.0f);
std::list<Creature*> beetlers = stalkers;
for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
(*itr)->CastSpell((*itr), SPELL_SUMMON_DUSTBONE_HORROR);
}
}
Trinity::Containers::RandomResize(beetlers, 9); // Holds the summoners of Jeweled Scarab
for (std::list<Creature*>::iterator itr = beetlers.begin(); itr != beetlers.end(); ++itr)
{
stalkers.remove((*itr)); // Remove it to prevent a single trigger from spawning multiple npcs.
(*itr)->CastSpell((*itr), SPELL_BEETLE_BURROW); // Cast visual
// Summon after 5 seconds.
(*itr)->m_Events.AddEventAtOffset(new SummonScarab((*itr), instance), 5s);
}
Trinity::Containers::RandomResize(stalkers, 2); // Holds the summoners of Dustbone Horror
for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
(*itr)->CastSpell((*itr), SPELL_SUMMON_DUSTBONE_HORROR);
void SetData(uint32 index, uint32 /*value*/) override
{
if (index == DATA_SUMMON_DEATHS)
{
++_summonDeaths;
if (_summonDeaths == 11) // All summons died
{
me->GetMap()->SetZoneWeather(AREA_TOMB_OF_THE_EARTHRAGER, WEATHER_STATE_FOG, 0.0f);
me->RemoveAurasDueToSpell(SPELL_PTAH_EXPLOSION);
events.SetPhase(PHASE_NORMAL);
events.ScheduleEvent(EVENT_RAGING_SMASH, 7s, 12s, 0, PHASE_NORMAL);
events.ScheduleEvent(EVENT_FLAME_BOLT, 15s, 0, PHASE_NORMAL);
events.ScheduleEvent(EVENT_EARTH_SPIKE, 16s, 21s, 0, PHASE_NORMAL);
}
}
}
void SetData(uint32 index, uint32 /*value*/) override
void JustEngagedWith(Unit* who) override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
Talk(SAY_AGGRO);
BossAI::JustEngagedWith(who);
}
void JustDied(Unit* /*killer*/) override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
Talk(SAY_DEATH);
_JustDied();
Cleanup();
}
void JustReachedHome() override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_JustReachedHome();
instance->SetBossState(BOSS_EARTHRAGER_PTAH, FAIL);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
if (index == DATA_SUMMON_DEATHS)
switch (eventId)
{
++_summonDeaths;
if (_summonDeaths == 11) // All summons died
{
me->GetMap()->SetZoneWeather(AREA_TOMB_OF_THE_EARTHRAGER, WEATHER_STATE_FOG, 0.0f);
me->RemoveAurasDueToSpell(SPELL_PTAH_EXPLOSION);
events.SetPhase(PHASE_NORMAL);
case EVENT_RAGING_SMASH:
DoCastVictim(SPELL_RAGING_SMASH);
events.ScheduleEvent(EVENT_RAGING_SMASH, 7s, 12s, 0, PHASE_NORMAL);
break;
case EVENT_FLAME_BOLT:
DoCast(me, SPELL_FLAME_BOLT);
events.ScheduleEvent(EVENT_FLAME_BOLT, 15s, 0, PHASE_NORMAL);
break;
case EVENT_EARTH_SPIKE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
DoCast(target, SPELL_EARTH_SPIKE_WARN);
events.ScheduleEvent(EVENT_EARTH_SPIKE, 16s, 21s, 0, PHASE_NORMAL);
}
break;
case EVENT_PTAH_EXPLODE:
DoCast(me, SPELL_PTAH_EXPLOSION);
break;
case EVENT_QUICKSAND:
// Spell not in DBC, it is not cast either, according to sniffs
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
if (Creature* quicksand = me->SummonCreature(NPC_QUICKSAND, *target))
quicksand->SetCreatedBySpell(SPELL_SUMMON_QUICKSAND);
events.ScheduleEvent(EVENT_QUICKSAND, 10s, 0, PHASE_DISPERSE);
break;
}
}
void JustEngagedWith(Unit* who) override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
Talk(SAY_AGGRO);
BossAI::JustEngagedWith(who);
}
if (events.GetPhaseMask() & PHASE_MASK_NORMAL) // Do not melee in the disperse phase
DoMeleeAttackIfReady();
}
void JustDied(Unit* /*killer*/) override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
Talk(SAY_DEATH);
_JustDied();
Cleanup();
}
protected:
uint8 _summonDeaths;
bool _hasDispersed;
};
void JustReachedHome() override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_JustReachedHome();
instance->SetBossState(BOSS_EARTHRAGER_PTAH, FAIL);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_RAGING_SMASH:
DoCastVictim(SPELL_RAGING_SMASH);
events.ScheduleEvent(EVENT_RAGING_SMASH, 7s, 12s, 0, PHASE_NORMAL);
break;
case EVENT_FLAME_BOLT:
DoCast(me, SPELL_FLAME_BOLT);
events.ScheduleEvent(EVENT_FLAME_BOLT, 15s, 0, PHASE_NORMAL);
break;
case EVENT_EARTH_SPIKE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
DoCast(target, SPELL_EARTH_SPIKE_WARN);
events.ScheduleEvent(EVENT_EARTH_SPIKE, 16s, 21s, 0, PHASE_NORMAL);
break;
case EVENT_PTAH_EXPLODE:
DoCast(me, SPELL_PTAH_EXPLOSION);
break;
case EVENT_QUICKSAND:
// Spell not in DBC, it is not cast either, according to sniffs
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
if (Creature* quicksand = me->SummonCreature(NPC_QUICKSAND, *target))
quicksand->SetCreatedBySpell(SPELL_SUMMON_QUICKSAND);
events.ScheduleEvent(EVENT_QUICKSAND, 10s, 0, PHASE_DISPERSE);
break;
}
}
if (events.GetPhaseMask() & PHASE_MASK_NORMAL) // Do not melee in the disperse phase
DoMeleeAttackIfReady();
}
protected:
uint8 _summonDeaths;
bool _hasDispersed;
};
CreatureAI* GetAI(Creature* creature) const override
class spell_earthrager_ptah_flame_bolt : public SpellScript
{
void FilterTargets(std::list<WorldObject*>& targets)
{
return GetHallsOfOriginationAI<boss_earthrager_ptahAI>(creature);
Trinity::Containers::RandomResize(targets, GetCaster()->GetMap()->IsHeroic() ? 3 : 2);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_earthrager_ptah_flame_bolt::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
class spell_earthrager_ptah_flame_bolt : public SpellScriptLoader
class spell_earthrager_ptah_explosion : public AuraScript
{
public:
spell_earthrager_ptah_flame_bolt() : SpellScriptLoader("spell_earthrager_ptah_flame_bolt") { }
class spell_earthrager_ptah_flame_bolt_SpellScript : public SpellScript
{
void FilterTargets(std::list<WorldObject*>& targets)
{
Trinity::Containers::RandomResize(targets, GetCaster()->GetMap()->IsHeroic() ? 3 : 2);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_earthrager_ptah_flame_bolt_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_earthrager_ptah_flame_bolt_SpellScript();
}
};
class spell_earthrager_ptah_explosion : public SpellScriptLoader
{
public:
spell_earthrager_ptah_explosion() : SpellScriptLoader("spell_earthrager_ptah_explosion") { }
class spell_earthrager_ptah_explosion_AuraScript : public AuraScript
void SetFlags(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
void SetFlags(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
if (Unit* ptah = GetCaster())
{
if (Unit* ptah = GetCaster())
{
ptah->SetUninteractible(true);
ptah->SetUnitFlag(UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
ptah->SetUnitFlag2(UNIT_FLAG2_FEIGN_DEATH);
}
ptah->SetUninteractible(true);
ptah->SetUnitFlag(UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
ptah->SetUnitFlag2(UNIT_FLAG2_FEIGN_DEATH);
}
}
void RemoveFlags(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* ptah = GetCaster())
{
ptah->SetUninteractible(false);
ptah->RemoveUnitFlag(UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
ptah->RemoveUnitFlag2(UNIT_FLAG2_FEIGN_DEATH);
}
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_earthrager_ptah_explosion_AuraScript::SetFlags, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
OnEffectRemove += AuraEffectRemoveFn(spell_earthrager_ptah_explosion_AuraScript::RemoveFlags, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
void RemoveFlags(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
return new spell_earthrager_ptah_explosion_AuraScript();
if (Unit* ptah = GetCaster())
{
ptah->SetUninteractible(false);
ptah->RemoveUnitFlag(UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
ptah->RemoveUnitFlag2(UNIT_FLAG2_FEIGN_DEATH);
}
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_earthrager_ptah_explosion::SetFlags, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
OnEffectRemove += AuraEffectRemoveFn(spell_earthrager_ptah_explosion::RemoveFlags, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
void AddSC_boss_earthrager_ptah()
{
new boss_earthrager_ptah();
new spell_earthrager_ptah_flame_bolt();
new spell_earthrager_ptah_explosion();
RegisterHallsOfOriginationCreatureAI(boss_earthrager_ptah);
RegisterSpellScript(spell_earthrager_ptah_flame_bolt);
RegisterSpellScript(spell_earthrager_ptah_explosion);
}

View File

@@ -74,309 +74,265 @@ enum Actions
ACTION_DISABLE_BEACON,
};
class boss_temple_guardian_anhuur : public CreatureScript
struct boss_temple_guardian_anhuur : public BossAI
{
public:
boss_temple_guardian_anhuur() : CreatureScript("boss_temple_guardian_anhuur") { }
struct boss_temple_guardian_anhuurAI : public BossAI
boss_temple_guardian_anhuur(Creature* creature) : BossAI(creature, BOSS_TEMPLE_GUARDIAN_ANHUUR)
{
boss_temple_guardian_anhuurAI(Creature* creature) : BossAI(creature, BOSS_TEMPLE_GUARDIAN_ANHUUR)
{
Initialize();
}
Initialize();
}
void Initialize()
{
_phase = PHASE_FIRST_SHIELD;
_oldPhase = PHASE_FIRST_SHIELD;
_beacons = 0;
}
void Initialize()
{
_phase = PHASE_FIRST_SHIELD;
_oldPhase = PHASE_FIRST_SHIELD;
_beacons = 0;
}
void CleanStalkers()
void CleanStalkers()
{
std::list<Creature*> stalkers;
GetCreatureListWithEntryInGrid(stalkers, me, NPC_CAVE_IN_STALKER, 100.0f);
for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
{
std::list<Creature*> stalkers;
GetCreatureListWithEntryInGrid(stalkers, me, NPC_CAVE_IN_STALKER, 100.0f);
for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
(*itr)->RemoveAurasDueToSpell(SPELL_BEAM_OF_LIGHT_RIGHT);
(*itr)->RemoveAurasDueToSpell(SPELL_BEAM_OF_LIGHT_LEFT);
}
}
void Reset() override
{
Initialize();
_Reset();
CleanStalkers();
me->RemoveAurasDueToSpell(SPELL_SHIELD_OF_LIGHT);
events.ScheduleEvent(EVENT_DIVINE_RECKONING, 10s, 12s);
events.ScheduleEvent(EVENT_BURNING_LIGHT, 12s);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
{
if ((me->HealthBelowPctDamaged(66, damage) && _phase == PHASE_FIRST_SHIELD) ||
(me->HealthBelowPctDamaged(33, damage) && _phase == PHASE_SECOND_SHIELD))
{
_beacons = 2;
_phase++; // Increase the phase
_oldPhase = _phase;
_phase = PHASE_SHIELDED;
me->InterruptNonMeleeSpells(true);
me->AttackStop();
DoCast(me, SPELL_TELEPORT);
DoCast(me, SPELL_SHIELD_OF_LIGHT);
DoCastAOE(SPELL_ACTIVATE_BEACONS);
GameObject* door = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_ANHUUR_DOOR));
if (door)
{
(*itr)->RemoveAurasDueToSpell(SPELL_BEAM_OF_LIGHT_RIGHT);
(*itr)->RemoveAurasDueToSpell(SPELL_BEAM_OF_LIGHT_LEFT);
std::list<Creature*> stalkers;
GetCreatureListWithEntryInGrid(stalkers, me, NPC_CAVE_IN_STALKER, 100.0f);
stalkers.remove_if(Trinity::HeightDifferenceCheck(door, 0.0f, false)); // Target only the bottom ones
for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
{
if ((*itr)->GetPositionX() > door->GetPositionX())
{
(*itr)->CastSpell((*itr), SPELL_SHIELD_VISUAL_LEFT, true);
(*itr)->CastSpell((*itr), SPELL_BEAM_OF_LIGHT_LEFT, true);
}
else
{
(*itr)->CastSpell((*itr), SPELL_SHIELD_VISUAL_RIGHT, true);
(*itr)->CastSpell((*itr), SPELL_BEAM_OF_LIGHT_RIGHT, true);
}
}
}
DoCast(me, SPELL_REVERBERATING_HYMN);
Talk(EMOTE_SHIELD);
Talk(SAY_SHIELD);
}
}
void DoAction(int32 action) override
{
if (action == ACTION_DISABLE_BEACON)
{
--_beacons;
if (!_beacons)
{
me->RemoveAurasDueToSpell(SPELL_SHIELD_OF_LIGHT);
Talk(EMOTE_UNSHIELD);
_phase = _oldPhase;
}
}
}
void Reset() override
{
Initialize();
_Reset();
CleanStalkers();
me->RemoveAurasDueToSpell(SPELL_SHIELD_OF_LIGHT);
events.ScheduleEvent(EVENT_DIVINE_RECKONING, 10s, 12s);
events.ScheduleEvent(EVENT_BURNING_LIGHT, 12s);
}
void JustEngagedWith(Unit* who) override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
Talk(SAY_AGGRO);
BossAI::JustEngagedWith(who);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
void JustDied(Unit* /*killer*/) override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
Talk(SAY_DEATH);
_JustDied();
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_KILL);
}
void JustReachedHome() override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_JustReachedHome();
instance->SetBossState(BOSS_TEMPLE_GUARDIAN_ANHUUR, FAIL);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom() || me->GetCurrentSpell(CURRENT_CHANNELED_SPELL) || _phase == PHASE_SHIELDED)
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
if ((me->HealthBelowPctDamaged(66, damage) && _phase == PHASE_FIRST_SHIELD) ||
(me->HealthBelowPctDamaged(33, damage) && _phase == PHASE_SECOND_SHIELD))
switch (eventId)
{
_beacons = 2;
_phase++; // Increase the phase
_oldPhase = _phase;
_phase = PHASE_SHIELDED;
me->InterruptNonMeleeSpells(true);
me->AttackStop();
DoCast(me, SPELL_TELEPORT);
DoCast(me, SPELL_SHIELD_OF_LIGHT);
DoCastAOE(SPELL_ACTIVATE_BEACONS);
GameObject* door = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_ANHUUR_DOOR));
if (door)
case EVENT_DIVINE_RECKONING:
DoCastVictim(SPELL_DIVINE_RECKONING);
events.ScheduleEvent(EVENT_DIVINE_RECKONING, 10s, 12s);
break;
case EVENT_BURNING_LIGHT:
{
Unit* unit = SelectTarget(SelectTargetMethod::Random, 0, NonTankTargetSelector(me));
if (!unit)
unit = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true);
DoCast(unit, SPELL_BURNING_LIGHT);
events.ScheduleEvent(EVENT_SEAR, 2s);
events.ScheduleEvent(EVENT_BURNING_LIGHT, 12s);
break;
}
case EVENT_SEAR:
{
Unit* target = me->FindNearestCreature(NPC_SEARING_LIGHT, 100.0f);
if (!target)
break;
std::list<Creature*> stalkers;
GetCreatureListWithEntryInGrid(stalkers, me, NPC_CAVE_IN_STALKER, 100.0f);
stalkers.remove_if(Trinity::HeightDifferenceCheck(ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_ANHUUR_DOOR)), 5.0f, true));
stalkers.remove_if(Trinity::HeightDifferenceCheck(door, 0.0f, false)); // Target only the bottom ones
for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
{
if ((*itr)->GetPositionX() > door->GetPositionX())
{
(*itr)->CastSpell((*itr), SPELL_SHIELD_VISUAL_LEFT, true);
(*itr)->CastSpell((*itr), SPELL_BEAM_OF_LIGHT_LEFT, true);
}
else
{
(*itr)->CastSpell((*itr), SPELL_SHIELD_VISUAL_RIGHT, true);
(*itr)->CastSpell((*itr), SPELL_BEAM_OF_LIGHT_RIGHT, true);
}
}
}
if (stalkers.empty())
break;
DoCast(me, SPELL_REVERBERATING_HYMN);
stalkers.sort(Trinity::ObjectDistanceOrderPred(target));
Talk(EMOTE_SHIELD);
Talk(SAY_SHIELD);
}
}
// Get the closest statue face (any of its eyes)
Creature* eye1 = stalkers.front();
stalkers.remove(eye1); // Remove the eye.
stalkers.sort(Trinity::ObjectDistanceOrderPred(eye1)); // Find the second eye.
Creature* eye2 = stalkers.front();
void DoAction(int32 action) override
{
if (action == ACTION_DISABLE_BEACON)
{
--_beacons;
if (!_beacons)
{
me->RemoveAurasDueToSpell(SPELL_SHIELD_OF_LIGHT);
Talk(EMOTE_UNSHIELD);
_phase = _oldPhase;
eye1->CastSpell(eye1, SPELL_SEARING_LIGHT, true);
eye2->CastSpell(eye2, SPELL_SEARING_LIGHT, true);
break;
}
}
}
void JustEngagedWith(Unit* who) override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
Talk(SAY_AGGRO);
BossAI::JustEngagedWith(who);
}
DoMeleeAttackIfReady();
}
void JustDied(Unit* /*killer*/) override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
Talk(SAY_DEATH);
_JustDied();
}
private:
uint8 _phase;
uint8 _oldPhase;
uint8 _beacons;
};
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_KILL);
}
void JustReachedHome() override
{
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_JustReachedHome();
instance->SetBossState(BOSS_TEMPLE_GUARDIAN_ANHUUR, FAIL);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom() || me->GetCurrentSpell(CURRENT_CHANNELED_SPELL) || _phase == PHASE_SHIELDED)
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_DIVINE_RECKONING:
DoCastVictim(SPELL_DIVINE_RECKONING);
events.ScheduleEvent(EVENT_DIVINE_RECKONING, 10s, 12s);
break;
case EVENT_BURNING_LIGHT:
{
Unit* unit = SelectTarget(SelectTargetMethod::Random, 0, NonTankTargetSelector(me));
if (!unit)
unit = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true);
DoCast(unit, SPELL_BURNING_LIGHT);
events.ScheduleEvent(EVENT_SEAR, 2s);
events.ScheduleEvent(EVENT_BURNING_LIGHT, 12s);
break;
}
case EVENT_SEAR:
{
Unit* target = me->FindNearestCreature(NPC_SEARING_LIGHT, 100.0f);
if (!target)
break;
std::list<Creature*> stalkers;
GetCreatureListWithEntryInGrid(stalkers, me, NPC_CAVE_IN_STALKER, 100.0f);
stalkers.remove_if(Trinity::HeightDifferenceCheck(ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_ANHUUR_DOOR)), 5.0f, true));
if (stalkers.empty())
break;
stalkers.sort(Trinity::ObjectDistanceOrderPred(target));
// Get the closest statue face (any of its eyes)
Creature* eye1 = stalkers.front();
stalkers.remove(eye1); // Remove the eye.
stalkers.sort(Trinity::ObjectDistanceOrderPred(eye1)); // Find the second eye.
Creature* eye2 = stalkers.front();
eye1->CastSpell(eye1, SPELL_SEARING_LIGHT, true);
eye2->CastSpell(eye2, SPELL_SEARING_LIGHT, true);
break;
}
}
}
DoMeleeAttackIfReady();
}
private:
uint8 _phase;
uint8 _oldPhase;
uint8 _beacons;
};
CreatureAI* GetAI(Creature* creature) const override
class spell_anhuur_shield_of_light : public SpellScript
{
void FilterTargets(std::list<WorldObject*>& targets)
{
return GetHallsOfOriginationAI<boss_temple_guardian_anhuurAI>(creature);
if (InstanceScript* const script = GetCaster()->GetInstanceScript())
{
if (GameObject* go = ObjectAccessor::GetGameObject(*GetCaster(), script->GetGuidData(DATA_ANHUUR_DOOR)))
{
targets.remove_if(Trinity::HeightDifferenceCheck(go, 5.0f, false));
targets.remove(GetCaster());
targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster()));
targets.resize(2);
}
}
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_anhuur_shield_of_light::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENTRY);
}
};
class spell_anhuur_shield_of_light : public SpellScriptLoader
class spell_anhuur_disable_beacon_beams : public SpellScript
{
public:
spell_anhuur_shield_of_light() : SpellScriptLoader("spell_anhuur_shield_of_light") { }
void HandleScript(SpellEffIndex /*effIndex*/)
{
GetHitUnit()->RemoveAurasDueToSpell(GetEffectValue());
}
class spell_anhuur_shield_of_light_SpellScript : public SpellScript
{
void FilterTargets(std::list<WorldObject*>& targets)
{
if (InstanceScript* const script = GetCaster()->GetInstanceScript())
{
if (GameObject* go = ObjectAccessor::GetGameObject(*GetCaster(), script->GetGuidData(DATA_ANHUUR_DOOR)))
{
targets.remove_if(Trinity::HeightDifferenceCheck(go, 5.0f, false));
targets.remove(GetCaster());
targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster()));
targets.resize(2);
}
}
}
void Notify(SpellEffIndex /*index*/)
{
GameObject* caster = GetGObjCaster();
if (!caster)
return;
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_anhuur_shield_of_light_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENTRY);
}
};
if (InstanceScript* instance = caster->GetInstanceScript())
if (Creature* anhuur = instance->GetCreature(BOSS_TEMPLE_GUARDIAN_ANHUUR))
if (CreatureAI* ai = anhuur->AI())
ai->DoAction(ACTION_DISABLE_BEACON);
}
SpellScript* GetSpellScript() const override
{
return new spell_anhuur_shield_of_light_SpellScript();
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_anhuur_disable_beacon_beams::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
OnEffectHit += SpellEffectFn(spell_anhuur_disable_beacon_beams::Notify, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
class spell_anhuur_disable_beacon_beams : public SpellScriptLoader
class spell_anhuur_divine_reckoning : public AuraScript
{
public:
spell_anhuur_disable_beacon_beams() : SpellScriptLoader("spell_anhuur_disable_beacon_beams") { }
class spell_anhuur_disable_beacon_beams_SpellScript : public SpellScript
{
void HandleScript(SpellEffIndex /*effIndex*/)
{
GetHitUnit()->RemoveAurasDueToSpell(GetEffectValue());
}
void Notify(SpellEffIndex /*index*/)
{
GameObject* caster = GetGObjCaster();
if (!caster)
return;
if (InstanceScript* instance = caster->GetInstanceScript())
if (Creature* anhuur = instance->GetCreature(BOSS_TEMPLE_GUARDIAN_ANHUUR))
if (CreatureAI* ai = anhuur->AI())
ai->DoAction(ACTION_DISABLE_BEACON);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_anhuur_disable_beacon_beams_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
OnEffectHit += SpellEffectFn(spell_anhuur_disable_beacon_beams_SpellScript::Notify, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_anhuur_disable_beacon_beams_SpellScript();
}
};
class spell_anhuur_divine_reckoning : public SpellScriptLoader
{
public:
spell_anhuur_divine_reckoning() : SpellScriptLoader("spell_anhuur_divine_reckoning") { }
class spell_anhuur_divine_reckoning_AuraScript : public AuraScript
void OnPeriodic(AuraEffect const* aurEff)
{
void OnPeriodic(AuraEffect const* aurEff)
if (Unit* caster = GetCaster())
{
if (Unit* caster = GetCaster())
{
CastSpellExtraArgs args;
args.AddSpellMod(SPELLVALUE_BASE_POINT0, aurEff->GetAmount());
caster->CastSpell(GetTarget(), aurEff->GetSpellEffectInfo().TriggerSpell, args);
}
CastSpellExtraArgs args;
args.AddSpellMod(SPELLVALUE_BASE_POINT0, aurEff->GetAmount());
caster->CastSpell(GetTarget(), aurEff->GetSpellEffectInfo().TriggerSpell, args);
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_anhuur_divine_reckoning_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
AuraScript* GetAuraScript() const override
void Register() override
{
return new spell_anhuur_divine_reckoning_AuraScript();
OnEffectPeriodic += AuraEffectPeriodicFn(spell_anhuur_divine_reckoning::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
void AddSC_boss_temple_guardian_anhuur()
{
new boss_temple_guardian_anhuur();
new spell_anhuur_shield_of_light();
new spell_anhuur_disable_beacon_beams();
new spell_anhuur_divine_reckoning();
RegisterHallsOfOriginationCreatureAI(boss_temple_guardian_anhuur);
RegisterSpellScript(spell_anhuur_shield_of_light);
RegisterSpellScript(spell_anhuur_disable_beacon_beams);
RegisterSpellScript(spell_anhuur_divine_reckoning);
}

View File

@@ -122,4 +122,6 @@ inline AI* GetHallsOfOriginationAI(Creature* creature)
return GetInstanceAI<AI>(creature, HoOScriptName);
}
#define RegisterHallsOfOriginationCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetHallsOfOriginationAI)
#endif // HALLS_OF_ORIGINATION_H