diff options
-rw-r--r-- | src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp | 382 |
1 files changed, 182 insertions, 200 deletions
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp index 8cb773bd768..d8a4fa39560 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp @@ -58,263 +58,245 @@ enum Achievements ACHIEV_QUICK_DEMISE_START_EVENT = 20382, }; -class boss_volazj : public CreatureScript +struct boss_volazj : public BossAI { -public: - boss_volazj() : CreatureScript("boss_volazj") { } + boss_volazj(Creature* creature) : BossAI(creature, DATA_HERALD_VOLAZJ), _insanityHandled(0) + { + Initialize(); + _instance = creature->GetInstanceScript(); + } - struct boss_volazjAI : public ScriptedAI + void Reset() override { - boss_volazjAI(Creature* creature) : ScriptedAI(creature), Summons(me) - { - Initialize(); - instance = creature->GetInstanceScript(); - } + BossAI::Reset(); - void Initialize() - { - uiMindFlayTimer = 8 * IN_MILLISECONDS; - uiShadowBoltVolleyTimer = 5 * IN_MILLISECONDS; - uiShiverTimer = 15 * IN_MILLISECONDS; - // Used for Insanity handling - insanityHandled = 0; - } + Initialize(); - InstanceScript* instance; + _instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); - uint32 uiMindFlayTimer; - uint32 uiShadowBoltVolleyTimer; - uint32 uiShiverTimer; - uint32 insanityHandled; - SummonList Summons; + // Visible for all players in insanity + me->SetPhaseMask((1|16|32|64|128|256), true); - // returns the percentage of health after taking the given damage. - uint32 GetHealthPct(uint32 damage) - { - if (damage > me->GetHealth()) - return 0; - return 100*(me->GetHealth()-damage)/me->GetMaxHealth(); - } + ResetPlayersPhaseMask(); - void DamageTaken(Unit* /*pAttacker*/, uint32 &damage) override - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - damage = 0; + // Cleanup + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetControlled(false, UNIT_STATE_STUNNED); + } + + void Initialize() + { + // Used for Insanity handling + _insanityHandled = 0; + } - if ((GetHealthPct(0) >= 66 && GetHealthPct(damage) < 66)|| - (GetHealthPct(0) >= 33 && GetHealthPct(damage) < 33)) + void ScheduleTasks() override + { + scheduler.Schedule(8s, [this](TaskContext task) { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_INSANITY, false); - } - } + DoCastVictim(SPELL_MIND_FLAY); + task.Repeat(20s); + }) + .Schedule(5s, [this](TaskContext task) + { + DoCastVictim(SPELL_SHADOW_BOLT_VOLLEY); + task.Repeat(); + }) + .Schedule(15s, [this](TaskContext task) + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) + DoCast(target, SPELL_SHIVER); + task.Repeat(); + }); + } + + // returns the percentage of health after taking the given damage. + uint32 GetHealthPct(uint32 damage) + { + if (damage > me->GetHealth()) + return 0; + return 100*(me->GetHealth()-damage)/me->GetMaxHealth(); + } - void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override + void DamageTaken(Unit* /*pAttacker*/, uint32 &damage) override + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + damage = 0; + + + if ((GetHealthPct(0) >= 66 && GetHealthPct(damage) < 66)|| + (GetHealthPct(0) >= 33 && GetHealthPct(damage) < 33)) { - if (spellInfo->Id == SPELL_INSANITY) - { - // Not good target or too many players - if (target->GetTypeId() != TYPEID_PLAYER || insanityHandled > 4) - return; - // First target - start channel visual and set self as unnattackable - if (!insanityHandled) - { - // Channel visual - DoCast(me, INSANITY_VISUAL, true); - // Unattackable - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetControlled(true, UNIT_STATE_STUNNED); - } - // phase mask - target->CastSpell(target, SPELL_INSANITY_TARGET+insanityHandled, true); - // summon twisted party members for this target - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) - { - Player* player = i->GetSource(); - if (!player || !player->IsAlive()) - continue; - // Summon clone - if (Unit* summon = me->SummonCreature(NPC_TWISTED_VISAGE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN)) - { - // clone - player->CastSpell(summon, SPELL_CLONE_PLAYER, true); - // set phase - summon->SetPhaseMask((1<<(4+insanityHandled)), true); - } - } - ++insanityHandled; - } + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_INSANITY, false); } + } - void ResetPlayersPhaseMask() + void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == SPELL_INSANITY) { + // Not good target or too many players + if (target->GetTypeId() != TYPEID_PLAYER || _insanityHandled > 4) + return; + // First target - start channel visual and set self as unnattackable + if (!_insanityHandled) + { + // Channel visual + DoCast(me, INSANITY_VISUAL, true); + // Unattackable + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetControlled(true, UNIT_STATE_STUNNED); + } + // phase mask + target->CastSpell(target, SPELL_INSANITY_TARGET + _insanityHandled, true); + // summon twisted party members for this target Map::PlayerList const& players = me->GetMap()->GetPlayers(); for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) { Player* player = i->GetSource(); - player->RemoveAurasDueToSpell(GetSpellForPhaseMask(player->GetPhaseMask())); + if (!player || !player->IsAlive()) + continue; + // Summon clone + if (Unit* summon = me->SummonCreature(NPC_TWISTED_VISAGE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN)) + { + // clone + player->CastSpell(summon, SPELL_CLONE_PLAYER, true); + // set phase + summon->SetPhaseMask((1<<(4 + _insanityHandled)), true); + } } + ++_insanityHandled; } + } - void Reset() override + void ResetPlayersPhaseMask() + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) { - Initialize(); - - instance->SetBossState(DATA_HERALD_VOLAZJ, NOT_STARTED); - instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); - - // Visible for all players in insanity - me->SetPhaseMask((1|16|32|64|128|256), true); - - ResetPlayersPhaseMask(); - - // Cleanup - Summons.DespawnAll(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetControlled(false, UNIT_STATE_STUNNED); + Player* player = i->GetSource(); + player->RemoveAurasDueToSpell(GetSpellForPhaseMask(player->GetPhaseMask())); } + } - void JustEngagedWith(Unit* /*who*/) override - { - Talk(SAY_AGGRO); + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + Talk(SAY_AGGRO); - instance->SetBossState(DATA_HERALD_VOLAZJ, IN_PROGRESS); - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); - } + _instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); + } - void JustSummoned(Creature* summon) override + uint32 GetSpellForPhaseMask(uint32 phase) + { + uint32 spell = 0; + switch (phase) { - Summons.Summon(summon); + case 16: + spell = SPELL_INSANITY_PHASING_1; + break; + case 32: + spell = SPELL_INSANITY_PHASING_2; + break; + case 64: + spell = SPELL_INSANITY_PHASING_3; + break; + case 128: + spell = SPELL_INSANITY_PHASING_4; + break; + case 256: + spell = SPELL_INSANITY_PHASING_5; + break; } + return spell; + } + + void SummonedCreatureDespawn(Creature* summon) override + { + BossAI::SummonedCreatureDespawn(summon); + + uint32 phase = summon->GetPhaseMask(); + uint32 nextPhase = 0; - uint32 GetSpellForPhaseMask(uint32 phase) + // Check if all summons in this phase killed + for (SummonList::const_iterator iter = summons.begin(); iter != summons.end(); ++iter) { - uint32 spell = 0; - switch (phase) + if (Creature* visage = ObjectAccessor::GetCreature(*me, *iter)) { - case 16: - spell = SPELL_INSANITY_PHASING_1; - break; - case 32: - spell = SPELL_INSANITY_PHASING_2; - break; - case 64: - spell = SPELL_INSANITY_PHASING_3; - break; - case 128: - spell = SPELL_INSANITY_PHASING_4; - break; - case 256: - spell = SPELL_INSANITY_PHASING_5; - break; + // Not all are dead + if (phase == visage->GetPhaseMask()) + return; + else + nextPhase = visage->GetPhaseMask(); } - return spell; } - void SummonedCreatureDespawn(Creature* summon) override + // Roll Insanity + uint32 spell = GetSpellForPhaseMask(phase); + uint32 spell2 = GetSpellForPhaseMask(nextPhase); + Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers(); + if (!PlayerList.isEmpty()) { - uint32 phase = summon->GetPhaseMask(); - uint32 nextPhase = 0; - Summons.Despawn(summon); - - // Check if all summons in this phase killed - for (SummonList::const_iterator iter = Summons.begin(); iter != Summons.end(); ++iter) - { - if (Creature* visage = ObjectAccessor::GetCreature(*me, *iter)) - { - // Not all are dead - if (phase == visage->GetPhaseMask()) - return; - else - nextPhase = visage->GetPhaseMask(); - } - } - - // Roll Insanity - uint32 spell = GetSpellForPhaseMask(phase); - uint32 spell2 = GetSpellForPhaseMask(nextPhase); - Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers(); - if (!PlayerList.isEmpty()) + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (Player* player = i->GetSource()) { - if (Player* player = i->GetSource()) + if (player->HasAura(spell)) { - if (player->HasAura(spell)) - { - player->RemoveAurasDueToSpell(spell); - if (spell2) // if there is still some different mask cast spell for it - player->CastSpell(player, spell2, true); - } + player->RemoveAurasDueToSpell(spell); + if (spell2) // if there is still some different mask cast spell for it + player->CastSpell(player, spell2, true); } } } } + } + + void UpdateAI(uint32 diff) override + { + //Return since we have no target + if (!UpdateVictim()) + return; - void UpdateAI(uint32 diff) override + if (_insanityHandled) { - //Return since we have no target - if (!UpdateVictim()) + if (!summons.empty()) return; - if (insanityHandled) - { - if (!Summons.empty()) - return; - - insanityHandled = 0; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetControlled(false, UNIT_STATE_STUNNED); - me->RemoveAurasDueToSpell(INSANITY_VISUAL); - } - - if (uiMindFlayTimer <= diff) - { - DoCastVictim(SPELL_MIND_FLAY); - uiMindFlayTimer = 20*IN_MILLISECONDS; - } else uiMindFlayTimer -= diff; - - if (uiShadowBoltVolleyTimer <= diff) - { - DoCastVictim(SPELL_SHADOW_BOLT_VOLLEY); - uiShadowBoltVolleyTimer = 5*IN_MILLISECONDS; - } else uiShadowBoltVolleyTimer -= diff; - - if (uiShiverTimer <= diff) - { - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) - DoCast(target, SPELL_SHIVER); - uiShiverTimer = 15*IN_MILLISECONDS; - } else uiShiverTimer -= diff; - - DoMeleeAttackIfReady(); + _insanityHandled = 0; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetControlled(false, UNIT_STATE_STUNNED); + me->RemoveAurasDueToSpell(INSANITY_VISUAL); } - void JustDied(Unit* /*killer*/) override + scheduler.Update(diff, [this] { - Talk(SAY_DEATH); - - instance->SetBossState(DATA_HERALD_VOLAZJ, DONE); + DoMeleeAttackIfReady(); + }); + } - Summons.DespawnAll(); - ResetPlayersPhaseMask(); - } + void JustDied(Unit* killer) override + { + BossAI::JustDied(killer); - void KilledUnit(Unit* who) override - { - if (who->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_SLAY); - } - }; + Talk(SAY_DEATH); + ResetPlayersPhaseMask(); + } - CreatureAI* GetAI(Creature* creature) const override + void KilledUnit(Unit* who) override { - return GetAhnKahetAI<boss_volazjAI>(creature); + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); } + +private: + InstanceScript* _instance; + + uint32 _insanityHandled; }; void AddSC_boss_volazj() { - new boss_volazj(); + RegisterAhnKahetCreatureAI(boss_volazj); } |