From 90543fd41db309d924a3d45939bd23cffb9f5b67 Mon Sep 17 00:00:00 2001 From: Carbenium Date: Sat, 1 Aug 2020 15:49:37 +0200 Subject: [PATCH] Scripts/AhnKahet: Update Herald Volazj to current coding standards * convert to BossAI * no functional changes --- .../Ahnkahet/boss_herald_volazj.cpp | 424 +++++++++--------- 1 file changed, 203 insertions(+), 221 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") { } - - struct boss_volazjAI : public ScriptedAI + boss_volazj(Creature* creature) : BossAI(creature, DATA_HERALD_VOLAZJ), _insanityHandled(0) { - boss_volazjAI(Creature* creature) : ScriptedAI(creature), Summons(me) - { - Initialize(); - instance = creature->GetInstanceScript(); - } + Initialize(); + _instance = creature->GetInstanceScript(); + } - void Initialize() - { - uiMindFlayTimer = 8 * IN_MILLISECONDS; - uiShadowBoltVolleyTimer = 5 * IN_MILLISECONDS; - uiShiverTimer = 15 * IN_MILLISECONDS; - // Used for Insanity handling - insanityHandled = 0; - } + void Reset() override + { + BossAI::Reset(); - InstanceScript* instance; + Initialize(); - uint32 uiMindFlayTimer; - uint32 uiShadowBoltVolleyTimer; - uint32 uiShiverTimer; - uint32 insanityHandled; - SummonList Summons; + _instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); - // 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(); - } + // Visible for all players in insanity + me->SetPhaseMask((1|16|32|64|128|256), true); - void DamageTaken(Unit* /*pAttacker*/, uint32 &damage) override - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - damage = 0; + ResetPlayersPhaseMask(); - if ((GetHealthPct(0) >= 66 && GetHealthPct(damage) < 66)|| - (GetHealthPct(0) >= 33 && GetHealthPct(damage) < 33)) + // Cleanup + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetControlled(false, UNIT_STATE_STUNNED); + } + + void Initialize() + { + // Used for Insanity handling + _insanityHandled = 0; + } + + void ScheduleTasks() override + { + scheduler.Schedule(8s, [this](TaskContext task) { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_INSANITY, false); - } - } - - void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override - { - if (spellInfo->Id == SPELL_INSANITY) + DoCastVictim(SPELL_MIND_FLAY); + task.Repeat(20s); + }) + .Schedule(5s, [this](TaskContext task) { - // 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; - } - } + 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(); + }); + } - void ResetPlayersPhaseMask() + // 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 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)) { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_INSANITY, false); + } + } + + 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())); - } - } - - void Reset() override - { - 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); - } - - void JustEngagedWith(Unit* /*who*/) override - { - Talk(SAY_AGGRO); - - instance->SetBossState(DATA_HERALD_VOLAZJ, IN_PROGRESS); - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); - } - - void JustSummoned(Creature* summon) override - { - Summons.Summon(summon); - } - - uint32 GetSpellForPhaseMask(uint32 phase) - { - uint32 spell = 0; - switch (phase) - { - 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 - { - 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)) + 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)) { - // Not all are dead - if (phase == visage->GetPhaseMask()) - return; - else - nextPhase = visage->GetPhaseMask(); + // clone + player->CastSpell(summon, SPELL_CLONE_PLAYER, true); + // set phase + summon->SetPhaseMask((1<<(4 + _insanityHandled)), true); } } + ++_insanityHandled; + } + } - // Roll Insanity - uint32 spell = GetSpellForPhaseMask(phase); - uint32 spell2 = GetSpellForPhaseMask(nextPhase); - Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers(); - if (!PlayerList.isEmpty()) + void ResetPlayersPhaseMask() + { + 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())); + } + } + + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + Talk(SAY_AGGRO); + + _instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); + } + + uint32 GetSpellForPhaseMask(uint32 phase) + { + uint32 spell = 0; + switch (phase) + { + 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; + + // 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)) { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + // 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) + { + 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 + void UpdateAI(uint32 diff) override + { + //Return since we have no target + if (!UpdateVictim()) + return; + + 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; + _insanityHandled = 0; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetControlled(false, UNIT_STATE_STUNNED); + me->RemoveAurasDueToSpell(INSANITY_VISUAL); + } + scheduler.Update(diff, [this] + { DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) override - { - Talk(SAY_DEATH); - - instance->SetBossState(DATA_HERALD_VOLAZJ, DONE); - - Summons.DespawnAll(); - ResetPlayersPhaseMask(); - } - - void KilledUnit(Unit* who) override - { - if (who->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_SLAY); - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetAhnKahetAI(creature); + }); } + + void JustDied(Unit* killer) override + { + BossAI::JustDied(killer); + + Talk(SAY_DEATH); + ResetPlayersPhaseMask(); + } + + void KilledUnit(Unit* who) override + { + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } + +private: + InstanceScript* _instance; + + uint32 _insanityHandled; }; void AddSC_boss_volazj() { - new boss_volazj(); + RegisterAhnKahetCreatureAI(boss_volazj); }