/* * Originally written by Xinef - Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: http://github.com/azerothcore/azerothcore-wotlk/LICENSE-AGPL */ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "black_temple.h" enum Supremus { EMOTE_NEW_TARGET = 0, EMOTE_PUNCH_GROUND = 1, EMOTE_GROUND_CRACK = 2, SPELL_SNARE_SELF = 41922, SPELL_MOLTEN_PUNCH = 40126, SPELL_HATEFUL_STRIKE = 41926, SPELL_VOLCANIC_ERUPTION = 40276, SPELL_VOLCANIC_ERUPTION_TRIGGER = 40117, SPELL_BERSERK = 45078, SPELL_CHARGE = 41581, NPC_SUPREMUS_PUNCH_STALKER = 23095, EVENT_SPELL_BERSERK = 1, EVENT_SPELL_HATEFUL_STRIKE = 2, EVENT_SPELL_MOLTEN_FLAMES = 3, EVENT_SWITCH_PHASE = 4, EVENT_SPELL_VOLCANIC_ERUPTION = 5, EVENT_SWITCH_TARGET = 6, EVENT_CHECK_DIST = 7, EVENT_GROUP_ABILITIES = 1 }; class boss_supremus : public CreatureScript { public: boss_supremus() : CreatureScript("boss_supremus") { } CreatureAI* GetAI(Creature* creature) const { return GetInstanceAI(creature); } struct boss_supremusAI : public BossAI { boss_supremusAI(Creature* creature) : BossAI(creature, DATA_SUPREMUS) { } void Reset() { BossAI::Reset(); } void EnterCombat(Unit* who) { BossAI::EnterCombat(who); SchedulePhase(false); events.ScheduleEvent(EVENT_SPELL_BERSERK, 900000); events.ScheduleEvent(EVENT_SPELL_MOLTEN_FLAMES, 4000); } void SchedulePhase(bool run) { events.CancelEventGroup(EVENT_GROUP_ABILITIES); events.ScheduleEvent(EVENT_SWITCH_PHASE, 60000); DoResetThreat(); if (!run) { events.ScheduleEvent(EVENT_SPELL_HATEFUL_STRIKE, 5000, EVENT_GROUP_ABILITIES); me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); me->RemoveAurasDueToSpell(SPELL_SNARE_SELF); } else { events.ScheduleEvent(EVENT_SPELL_VOLCANIC_ERUPTION, 5000, EVENT_GROUP_ABILITIES); events.ScheduleEvent(EVENT_SWITCH_TARGET, 0, EVENT_GROUP_ABILITIES); events.ScheduleEvent(EVENT_CHECK_DIST, 0, EVENT_GROUP_ABILITIES); me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); me->CastSpell(me, SPELL_SNARE_SELF, true); } } void JustDied(Unit* killer) { BossAI::JustDied(killer); } void JustSummoned(Creature* summon) { summons.Summon(summon); if (summon->GetEntry() == NPC_SUPREMUS_PUNCH_STALKER) { summon->ToTempSummon()->InitStats(20000); if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) summon->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f, MOTION_SLOT_CONTROLLED); } else summon->CastSpell(summon, SPELL_VOLCANIC_ERUPTION_TRIGGER, true); } void SummonedCreatureDespawn(Creature* summon) { summons.Despawn(summon); } Unit* FindHatefulStrikeTarget() { Unit* target = NULL; ThreatContainer::StorageType const &threatlist = me->getThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) { Unit* unit = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()); if (unit && me->IsWithinMeleeRange(unit)) if (!target || unit->GetHealth() > target->GetHealth()) target = unit; } return target; } void UpdateAI(uint32 diff) { if (!UpdateVictim()) return; events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) return; switch (events.ExecuteEvent()) { case EVENT_SPELL_BERSERK: me->CastSpell(me, SPELL_BERSERK, true); break; case EVENT_SPELL_HATEFUL_STRIKE: if (Unit* target = FindHatefulStrikeTarget()) me->CastSpell(target, SPELL_HATEFUL_STRIKE, false); events.ScheduleEvent(EVENT_SPELL_HATEFUL_STRIKE, urand(1500, 3000), EVENT_GROUP_ABILITIES); break; case EVENT_SPELL_MOLTEN_FLAMES: me->CastSpell(me, SPELL_MOLTEN_PUNCH, false); events.ScheduleEvent(EVENT_SPELL_MOLTEN_FLAMES, 20000, EVENT_GROUP_ABILITIES); break; case EVENT_SWITCH_PHASE: SchedulePhase(!me->HasAura(SPELL_SNARE_SELF)); break; case EVENT_SWITCH_TARGET: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) { DoResetThreat(); me->AddThreat(target, 5000000.0f); Talk(EMOTE_NEW_TARGET); } events.ScheduleEvent(EVENT_SWITCH_TARGET, 10000, EVENT_GROUP_ABILITIES); break; case EVENT_CHECK_DIST: if (me->GetDistance(me->GetVictim()) > 40.0f) { Talk(EMOTE_PUNCH_GROUND); me->CastSpell(me->GetVictim(), SPELL_CHARGE, true); events.ScheduleEvent(EVENT_CHECK_DIST, 5000, EVENT_GROUP_ABILITIES); break; } events.ScheduleEvent(EVENT_CHECK_DIST, 1, EVENT_GROUP_ABILITIES); break; case EVENT_SPELL_VOLCANIC_ERUPTION: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) { me->CastSpell(target, SPELL_VOLCANIC_ERUPTION, true); Talk(EMOTE_GROUND_CRACK); } events.ScheduleEvent(EVENT_SPELL_VOLCANIC_ERUPTION, urand(10000, 18000), EVENT_GROUP_ABILITIES); break; } DoMeleeAttackIfReady(); EnterEvadeIfOutOfCombatArea(); } bool CheckEvadeIfOutOfCombatArea() const { return me->GetPositionX() < 565 || me->GetPositionX() > 865 || me->GetPositionY() < 545 || me->GetPositionY() > 1000; } }; }; void AddSC_boss_supremus() { new boss_supremus(); }