diff options
Diffstat (limited to 'src/server')
| -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);  } | 
