diff --git a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/ahnkahet.h b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/ahnkahet.h index cf90ecf79..438ab4647 100644 --- a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/ahnkahet.h +++ b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/ahnkahet.h @@ -71,4 +71,7 @@ inline AI* GetAhnKahetAI(T* obj) return GetInstanceAI(obj, AhnKahetScriptName); } +#define RegisterAhnKahetCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetAhnKahetAI) +#define RegisterAhnKahetGameObjectAI(ai_name) RegisterGameObjectAIWithFactory(ai_name, GetAhnKahetAI) + #endif // DEF_AHNKAHET_H diff --git a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_amanitar.cpp b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_amanitar.cpp index cf41adc7c..2d8b5e39d 100644 --- a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_amanitar.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_amanitar.cpp @@ -99,288 +99,253 @@ Position const MushroomPositions[MAX_MUSHROOMS_COUNT] = { 398.2797f, -851.8694f, -68.84419f, 0.5759587f } }; -class boss_amanitar : public CreatureScript +struct boss_amanitar : public BossAI { -public: - boss_amanitar() : CreatureScript("boss_amanitar") + boss_amanitar(Creature* creature) : BossAI(creature, DATA_AMANITAR), mushroomsSummoned(false) { + creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + creature->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); } - struct boss_amanitarAI : public BossAI + void Reset() override { - boss_amanitarAI(Creature* creature) : BossAI(creature, DATA_AMANITAR), mushroomsSummoned(false) + _Reset(); + _mushroomsDeque.clear(); + mushroomsSummoned = false; + } + + void EnterCombat(Unit* /*attacker*/) override + { + events.ScheduleEvent(EVENT_ROOTS, urand(5000, 9000)); + events.ScheduleEvent(EVENT_BASH, urand(10000, 14000)); + events.ScheduleEvent(EVENT_BOLT, urand(15000, 20000)); + events.ScheduleEvent(EVENT_MINI, 1000); + events.ScheduleEvent(EVENT_RESPAWN, 40000, 60000); + } + + void JustDied(Unit* /*Killer*/) override + { + _JustDied(); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI); + } + + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + } + + void SummonedCreatureDies(Creature* summon, Unit* killer) override + { + _mushroomsDeque.push_back(summon->GetPosition()); + BossAI::SummonedCreatureDies(summon, killer); + } + + void EnterEvadeMode() override + { + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI); + BossAI::EnterEvadeMode(); + } + + void ExecuteEvent(uint32 eventId) override + { + switch (eventId) { - creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); - creature->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); + case EVENT_RESPAWN: + { + while (!_mushroomsDeque.empty()) + { + SummonMushroom(_mushroomsDeque.front()); + _mushroomsDeque.pop_front(); + } + + events.RepeatEvent(urand(40000, 60000)); + break; + } + case EVENT_ROOTS: + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoCast(pTarget, SPELL_ENTANGLING_ROOTS, false); + } + + events.RepeatEvent(urand(10000, 15000)); + break; + } + case EVENT_BASH: + { + DoCastVictim(SPELL_BASH, false); + events.RepeatEvent(urand(15000, 20000)); + break; + } + case EVENT_BOLT: + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoCast(pTarget, SPELL_VENOM_BOLT_VOLLEY, false); + } + + events.RepeatEvent(urand(15000, 20000)); + break; + } + case EVENT_REMOVE_MUSHROOM_POWER: + { + DoCastAOE(SPELL_REMOVE_MUSHROOM_POWER, true); + events.RescheduleEvent(EVENT_MINI, 1000); + break; + } + case EVENT_MINI: + { + if (!mushroomsSummoned) + { + mushroomsSummoned = true; + for (uint8 i = 0; i < MAX_MUSHROOMS_COUNT; ++i) + { + SummonMushroom(MushroomPositions[i]); + } + } + + if (SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_MINI)) + { + DoCastSelf(SPELL_REMOVE_MUSHROOM_POWER, true); + DoCastAOE(SPELL_MINI); + events.RescheduleEvent(EVENT_REMOVE_MUSHROOM_POWER, 29000); + } + else + { + events.RepeatEvent(1000); + } + + break; + } + } + } + +private: + std::deque _mushroomsDeque; + bool mushroomsSummoned; + + void SummonMushroom(Position const& pos) + { + me->SummonCreature(roll_chance_i(40) ? NPC_HEALTHY_MUSHROOM : NPC_POISONOUS_MUSHROOM, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 4000); + } +}; + +struct npc_amanitar_mushrooms : public ScriptedAI +{ + npc_amanitar_mushrooms(Creature* pCreature) : ScriptedAI(pCreature) + { + SetCombatMovement(false); + + //TODO: this prolly needs to be done in database + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->SetRegeneratingHealth(false); + } + + // Disabled events + void EnterCombat(Unit* /*who*/) override {} + void AttackStart(Unit* /*victim*/) override {} + void EnterEvadeMode() override {} + + void Reset() override + { + me->SetReactState(REACT_PASSIVE); + DoCastSelf(SPELL_PUTRID_MUSHROOM); + + if (me->GetEntry() == NPC_POISONOUS_MUSHROOM) + { + DoCastSelf(SPELL_POISONOUS_MUSHROOM_VISUAL_AURA, true); + } + else + { + DoCastSelf(SPELL_HEALTHY_MUSHROOM_VISUAL_AURA, true); } - void Reset() override - { - _Reset(); - _mushroomsDeque.clear(); - mushroomsSummoned = false; - } + events.ScheduleEvent(EVENT_GROW, 800); - void EnterCombat(Unit* /*attacker*/) override + if (me->GetEntry() == NPC_POISONOUS_MUSHROOM) { - events.ScheduleEvent(EVENT_ROOTS, urand(5000, 9000)); - events.ScheduleEvent(EVENT_BASH, urand(10000, 14000)); - events.ScheduleEvent(EVENT_BOLT, urand(15000, 20000)); - events.ScheduleEvent(EVENT_MINI, 1000); - events.ScheduleEvent(EVENT_RESPAWN, 40000, 60000); + events.ScheduleEvent(EVENT_CHECK_PLAYER, 250); } + } - void JustDied(Unit* /*Killer*/) override + void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override + { + if (me->GetEntry() == NPC_HEALTHY_MUSHROOM && damage >= me->GetHealth()) { - _JustDied(); - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI); + DoCastSelf(SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS, true); } + } - void JustSummoned(Creature* summon) override - { - summons.Summon(summon); - } + void UpdateAI(uint32 diff) override + { + if (events.Empty()) + return; - void SummonedCreatureDies(Creature* summon, Unit* killer) override - { - _mushroomsDeque.push_back(summon->GetPosition()); - BossAI::SummonedCreatureDies(summon, killer); - } - - void EnterEvadeMode() override - { - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI); - BossAI::EnterEvadeMode(); - } - - void ExecuteEvent(uint32 eventId) override + events.Update(diff); + while (uint32 const eventId = events.ExecuteEvent()) { switch (eventId) { - case EVENT_RESPAWN: + case EVENT_GROW: { - while (!_mushroomsDeque.empty()) - { - SummonMushroom(_mushroomsDeque.front()); - _mushroomsDeque.pop_front(); - } - - events.RepeatEvent(urand(40000, 60000)); + DoCastSelf(SPELL_GROW); break; } - case EVENT_ROOTS: + case EVENT_CHECK_PLAYER: { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + if (Player* plr = me->SelectNearestPlayer(2.0f)) { - DoCast(pTarget, SPELL_ENTANGLING_ROOTS, false); - } - - events.RepeatEvent(urand(10000, 15000)); - break; - } - case EVENT_BASH: - { - DoCastVictim(SPELL_BASH, false); - events.RepeatEvent(urand(15000, 20000)); - break; - } - case EVENT_BOLT: - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoCast(pTarget, SPELL_VENOM_BOLT_VOLLEY, false); - } - - events.RepeatEvent(urand(15000, 20000)); - break; - } - case EVENT_REMOVE_MUSHROOM_POWER: - { - DoCastAOE(SPELL_REMOVE_MUSHROOM_POWER, true); - events.RescheduleEvent(EVENT_MINI, 1000); - break; - } - case EVENT_MINI: - { - if (!mushroomsSummoned) - { - mushroomsSummoned = true; - for (uint8 i = 0; i < MAX_MUSHROOMS_COUNT; ++i) - { - SummonMushroom(MushroomPositions[i]); - } - } - - if (SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_MINI)) - { - DoCastSelf(SPELL_REMOVE_MUSHROOM_POWER, true); - DoCastAOE(SPELL_MINI); - events.RescheduleEvent(EVENT_REMOVE_MUSHROOM_POWER, 29000); + plr->RemoveAurasDueToSpell(SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS); + DoCastSelf(SPELL_POISONOUS_MUSHROOM_VISUAL_AREA); + DoCastSelf(SPELL_POISONOUS_MUSHROOM_POISON_CLOUD); + DoCastSelf(SPELL_SHRINK); + events.ScheduleEvent(EVENT_KILLSELF, 4000); } else { - events.RepeatEvent(1000); + events.RepeatEvent(250); } break; } - } - } - - private: - std::deque _mushroomsDeque; - bool mushroomsSummoned; - - void SummonMushroom(Position const& pos) - { - me->SummonCreature(roll_chance_i(40) ? NPC_HEALTHY_MUSHROOM : NPC_POISONOUS_MUSHROOM, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 4000); - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetAhnKahetAI(creature); - } -}; - -class npc_amanitar_mushrooms : public CreatureScript -{ -public: - npc_amanitar_mushrooms() : CreatureScript("npc_amanitar_mushrooms") { } - - struct npc_amanitar_mushroomsAI : public ScriptedAI - { - npc_amanitar_mushroomsAI(Creature* pCreature) : ScriptedAI(pCreature) - { - SetCombatMovement(false); - - //TODO: this prolly needs to be done in database - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pCreature->SetRegeneratingHealth(false); - } - - // Disabled events - void EnterCombat(Unit* /*who*/) override {} - void AttackStart(Unit* /*victim*/) override {} - void EnterEvadeMode() override {} - - void Reset() override - { - me->SetReactState(REACT_PASSIVE); - DoCastSelf(SPELL_PUTRID_MUSHROOM); - - if (me->GetEntry() == NPC_POISONOUS_MUSHROOM) - { - DoCastSelf(SPELL_POISONOUS_MUSHROOM_VISUAL_AURA, true); - } - else - { - DoCastSelf(SPELL_HEALTHY_MUSHROOM_VISUAL_AURA, true); - } - - events.ScheduleEvent(EVENT_GROW, 800); - - if (me->GetEntry() == NPC_POISONOUS_MUSHROOM) - { - events.ScheduleEvent(EVENT_CHECK_PLAYER, 250); - } - } - - void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override - { - if (me->GetEntry() == NPC_HEALTHY_MUSHROOM && damage >= me->GetHealth()) - { - DoCastSelf(SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS, true); - } - } - - void UpdateAI(uint32 diff) override - { - if (events.Empty()) - return; - - events.Update(diff); - while (uint32 const eventId = events.ExecuteEvent()) - { - switch (eventId) + case EVENT_KILLSELF: { - case EVENT_GROW: - { - DoCastSelf(SPELL_GROW); - break; - } - case EVENT_CHECK_PLAYER: - { - if (Player* plr = me->SelectNearestPlayer(2.0f)) - { - plr->RemoveAurasDueToSpell(SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS); - DoCastSelf(SPELL_POISONOUS_MUSHROOM_VISUAL_AREA); - DoCastSelf(SPELL_POISONOUS_MUSHROOM_POISON_CLOUD); - DoCastSelf(SPELL_SHRINK); - events.ScheduleEvent(EVENT_KILLSELF, 4000); - } - else - { - events.RepeatEvent(250); - } - - break; - } - case EVENT_KILLSELF: - { - me->DisappearAndDie(); - break; - } + me->DisappearAndDie(); + break; } } } - - private: - EventMap events; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetAhnKahetAI(creature); } + +private: + EventMap events; }; // 57283 Remove Mushroom Power -class spell_amanitar_remove_mushroom_power : public SpellScriptLoader +class spell_amanitar_remove_mushroom_power : public AuraScript { -public: - spell_amanitar_remove_mushroom_power() : SpellScriptLoader("spell_amanitar_remove_mushroom_power") { } + PrepareAuraScript(spell_amanitar_remove_mushroom_power); - class spell_amanitar_remove_mushroom_power_AuraScript : public AuraScript + void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - PrepareAuraScript(spell_amanitar_remove_mushroom_power_AuraScript); - - void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + if (Unit* target = GetTarget()) { - if (Unit* target = GetTarget()) - { - target->RemoveAurasDueToSpell(SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS); - } + target->RemoveAurasDueToSpell(SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS); } + } - void Register() override - { - OnEffectApply += AuraEffectApplyFn(spell_amanitar_remove_mushroom_power_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const + void Register() override { - return new spell_amanitar_remove_mushroom_power_AuraScript(); + OnEffectApply += AuraEffectApplyFn(spell_amanitar_remove_mushroom_power::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); } }; void AddSC_boss_amanitar() { - new boss_amanitar(); - new npc_amanitar_mushrooms(); + RegisterAhnKahetCreatureAI(boss_amanitar); + RegisterAhnKahetCreatureAI(npc_amanitar_mushrooms); // Spells - new spell_amanitar_remove_mushroom_power(); + RegisterSpellScript(spell_amanitar_remove_mushroom_power); } diff --git a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_elder_nadox.cpp b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_elder_nadox.cpp index 907c308e0..8f27998cf 100644 --- a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_elder_nadox.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_elder_nadox.cpp @@ -69,336 +69,303 @@ enum Yells EMOTE_HATCHES = 4 }; -class boss_elder_nadox : public CreatureScript +struct boss_elder_nadox : public BossAI { -public: - boss_elder_nadox() : CreatureScript("boss_elder_nadox") { } - - struct boss_elder_nadoxAI : public BossAI + boss_elder_nadox(Creature* creature) : BossAI(creature, DATA_PRINCE_TALDARAM), + guardianSummoned(false), + respectYourElders(true) { - boss_elder_nadoxAI(Creature* creature) : BossAI(creature, DATA_PRINCE_TALDARAM), - guardianSummoned(false), - respectYourElders(true) + } + + void Reset() override + { + _Reset(); + + // Clear eggs data + swarmEggs.clear(); + guardianEggs.clear(); + previousSwarmEgg_GUID.Clear(); + guardianSummoned = false; + respectYourElders = true; + } + + void EnterCombat(Unit * /*who*/) override + { + _EnterCombat(); + Talk(SAY_AGGRO); + + events.ScheduleEvent(EVENT_SWARMER, 10000); + events.ScheduleEvent(EVENT_CHECK_HOME, 2000); + events.ScheduleEvent(EVENT_PLAGUE, urand(5000, 8000)); + + if (IsHeroic()) { + events.ScheduleEvent(EVENT_BROOD_RAGE, 5000); } - void Reset() override + // Cache eggs + std::list eggs; + // Swarm eggs + me->GetCreatureListWithEntryInGrid(eggs, NPC_AHNKAHAR_SWARM_EGG, 250.0f); + if (!eggs.empty()) { - _Reset(); - - // Clear eggs data - swarmEggs.clear(); - guardianEggs.clear(); - previousSwarmEgg_GUID.Clear(); - guardianSummoned = false; - respectYourElders = true; - } - - void EnterCombat(Unit * /*who*/) override - { - _EnterCombat(); - Talk(SAY_AGGRO); - - events.ScheduleEvent(EVENT_SWARMER, 10000); - events.ScheduleEvent(EVENT_CHECK_HOME, 2000); - events.ScheduleEvent(EVENT_PLAGUE, urand(5000, 8000)); - - if (IsHeroic()) + for (Creature* const egg : eggs) { - events.ScheduleEvent(EVENT_BROOD_RAGE, 5000); - } - - // Cache eggs - std::list eggs; - // Swarm eggs - me->GetCreatureListWithEntryInGrid(eggs, NPC_AHNKAHAR_SWARM_EGG, 250.0f); - if (!eggs.empty()) - { - for (Creature* const egg : eggs) + if (egg) { - if (egg) - { - swarmEggs.push_back(egg->GetGUID()); - } - } - } - - eggs.clear(); - - // Guardian eggs - me->GetCreatureListWithEntryInGrid(eggs, NPC_AHNKAHAR_GUARDIAN_EGG, 250.0f); - if (!eggs.empty()) - { - for (Creature* const egg : eggs) - { - if (egg) - { - guardianEggs.push_back(egg->GetGUID()); - } + swarmEggs.push_back(egg->GetGUID()); } } } - void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override + eggs.clear(); + + // Guardian eggs + me->GetCreatureListWithEntryInGrid(eggs, NPC_AHNKAHAR_GUARDIAN_EGG, 250.0f); + if (!eggs.empty()) { - if (summon->GetEntry() == NPC_AHNKAHAR_GUARDIAN) + for (Creature* const egg : eggs) { - respectYourElders = false; + if (egg) + { + guardianEggs.push_back(egg->GetGUID()); + } + } + } + } + + void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override + { + if (summon->GetEntry() == NPC_AHNKAHAR_GUARDIAN) + { + respectYourElders = false; + } + } + + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + { + Talk(SAY_SLAY); + } + } + + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + Talk(SAY_DEATH); + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*school*/) override + { + if (!guardianSummoned && me->HealthBelowPctDamaged(55, damage)) + { + SummonHelpers(false); + guardianSummoned = true; + } + } + + uint32 GetData(uint32 type) const override + { + if (type == DATA_RESPECT_YOUR_ELDERS) + { + return respectYourElders ? 1 : 0; + } + + return 0; + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + { + return; + } + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + { + return; + } + + while (uint32 const eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_BROOD_RAGE: + { + if (Creature* pSwarmer = me->FindNearestCreature(NPC_AHNKAHAR_SWARMER, 40, true)) + DoCast(pSwarmer, SPELL_BROOD_RAGE_H, true); + + events.RepeatEvent(10000); + break; + } + case EVENT_PLAGUE: + { + DoCastVictim(SPELL_BROOD_PLAGUE, false); + events.RepeatEvent(urand(12000, 17000)); + break; + } + case EVENT_SWARMER: + { + SummonHelpers(true); + events.RepeatEvent(10000); + break; + } + case EVENT_CHECK_HOME: + { + if (!me->HasAura(SPELL_ENRAGE) && (me->GetPositionZ() < 24.0f || !me->GetHomePosition().IsInDist(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 110.0f))) + { + DoCastSelf(SPELL_ENRAGE, true); + } + break; + } } } - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - { - Talk(SAY_SLAY); - } - } + DoMeleeAttackIfReady(); + } - void JustDied(Unit* /*killer*/) override - { - _JustDied(); - Talk(SAY_DEATH); - } +private: + GuidList swarmEggs; + GuidList guardianEggs; + ObjectGuid previousSwarmEgg_GUID; // This will prevent casting summoning spells on same egg twice + bool guardianSummoned; + bool respectYourElders; - void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*school*/) override + void SummonHelpers(bool swarm) + { + if (swarm) { - if (!guardianSummoned && me->HealthBelowPctDamaged(55, damage)) - { - SummonHelpers(false); - guardianSummoned = true; - } - } - - uint32 GetData(uint32 type) const override - { - if (type == DATA_RESPECT_YOUR_ELDERS) - { - return respectYourElders ? 1 : 0; - } - - return 0; - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) + if (swarmEggs.empty()) { return; } - events.Update(diff); + // Make a copy of guid list + GuidList swarmEggs2 = swarmEggs; - if (me->HasUnitState(UNIT_STATE_CASTING)) + // Remove previous egg + if (previousSwarmEgg_GUID) + { + std::list::iterator itr = std::find(swarmEggs2.begin(), swarmEggs2.end(), previousSwarmEgg_GUID); + if (itr != swarmEggs2.end()) + { + swarmEggs2.erase(itr); + } + } + + if (swarmEggs2.empty()) { return; } - while (uint32 const eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_BROOD_RAGE: - { - if (Creature* pSwarmer = me->FindNearestCreature(NPC_AHNKAHAR_SWARMER, 40, true)) - DoCast(pSwarmer, SPELL_BROOD_RAGE_H, true); + previousSwarmEgg_GUID = Acore::Containers::SelectRandomContainerElement(swarmEggs2); - events.RepeatEvent(10000); - break; - } - case EVENT_PLAGUE: - { - DoCastVictim(SPELL_BROOD_PLAGUE, false); - events.RepeatEvent(urand(12000, 17000)); - break; - } - case EVENT_SWARMER: - { - SummonHelpers(true); - events.RepeatEvent(10000); - break; - } - case EVENT_CHECK_HOME: - { - if (!me->HasAura(SPELL_ENRAGE) && (me->GetPositionZ() < 24.0f || !me->GetHomePosition().IsInDist(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 110.0f))) - { - DoCastSelf(SPELL_ENRAGE, true); - } - break; - } - } + if (Creature* egg = ObjectAccessor::GetCreature(*me, previousSwarmEgg_GUID)) + { + egg->CastSpell(egg, SPELL_SUMMON_SWARMERS, true, nullptr, nullptr, me->GetGUID()); } - DoMeleeAttackIfReady(); + if (roll_chance_f(33)) + { + Talk(SAY_EGG_SAC); + } } - - private: - GuidList swarmEggs; - GuidList guardianEggs; - ObjectGuid previousSwarmEgg_GUID; // This will prevent casting summoning spells on same egg twice - bool guardianSummoned; - bool respectYourElders; - - void SummonHelpers(bool swarm) + else { - if (swarm) + if (guardianEggs.empty()) { - if (swarmEggs.empty()) - { - return; - } - - // Make a copy of guid list - GuidList swarmEggs2 = swarmEggs; - - // Remove previous egg - if (previousSwarmEgg_GUID) - { - std::list::iterator itr = std::find(swarmEggs2.begin(), swarmEggs2.end(), previousSwarmEgg_GUID); - if (itr != swarmEggs2.end()) - { - swarmEggs2.erase(itr); - } - } - - if (swarmEggs2.empty()) - { - return; - } - - previousSwarmEgg_GUID = Acore::Containers::SelectRandomContainerElement(swarmEggs2); - - if (Creature* egg = ObjectAccessor::GetCreature(*me, previousSwarmEgg_GUID)) - { - egg->CastSpell(egg, SPELL_SUMMON_SWARMERS, true, nullptr, nullptr, me->GetGUID()); - } - - if (roll_chance_f(33)) - { - Talk(SAY_EGG_SAC); - } + return; } - else + + ObjectGuid const& guardianEggGUID = Acore::Containers::SelectRandomContainerElement(guardianEggs); + if (Creature* egg = ObjectAccessor::GetCreature(*me, guardianEggGUID)) { - if (guardianEggs.empty()) - { - return; - } + egg->CastSpell(egg, SPELL_SUMMON_SWARM_GUARD, true, nullptr, nullptr, me->GetGUID()); + } - ObjectGuid const& guardianEggGUID = Acore::Containers::SelectRandomContainerElement(guardianEggs); - if (Creature* egg = ObjectAccessor::GetCreature(*me, guardianEggGUID)) - { - egg->CastSpell(egg, SPELL_SUMMON_SWARM_GUARD, true, nullptr, nullptr, me->GetGUID()); - } + Talk(EMOTE_HATCHES, me); - Talk(EMOTE_HATCHES, me); - - if (roll_chance_f(33)) - { - Talk(SAY_EGG_SAC); - } + if (roll_chance_f(33)) + { + Talk(SAY_EGG_SAC); } } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetAhnKahetAI(creature); } }; -class npc_ahnkahar_nerubian : public CreatureScript +struct npc_ahnkahar_nerubian : public ScriptedAI { -public: - npc_ahnkahar_nerubian() : CreatureScript("npc_ahnkahar_nerubian") { } + npc_ahnkahar_nerubian(Creature* c) : ScriptedAI(c) { } - struct npc_ahnkahar_nerubianAI : public ScriptedAI + void Reset() override { - npc_ahnkahar_nerubianAI(Creature* c) : ScriptedAI(c) { } - - void Reset() override - { - DoCastSelf(me->GetEntry() == NPC_AHNKAHAR_GUARDIAN ? SPELL_GUARDIAN_AURA : SPELL_SWARMER_AURA, true); - uiSprintTimer = 10000; - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - if (uiSprintTimer <= diff) - { - DoCastSelf(SPELL_SPRINT, false); - uiSprintTimer = 15000; - } - else - uiSprintTimer -= diff; - - DoMeleeAttackIfReady(); - } - - private: - uint32 uiSprintTimer; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetAhnKahetAI(creature); + DoCastSelf(me->GetEntry() == NPC_AHNKAHAR_GUARDIAN ? SPELL_GUARDIAN_AURA : SPELL_SWARMER_AURA, true); + uiSprintTimer = 10000; } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (uiSprintTimer <= diff) + { + DoCastSelf(SPELL_SPRINT, false); + uiSprintTimer = 15000; + } + else + uiSprintTimer -= diff; + + DoMeleeAttackIfReady(); + } + +private: + uint32 uiSprintTimer; }; -class spell_ahn_kahet_swarmer_aura : public SpellScriptLoader +class spell_ahn_kahet_swarmer_aura : public SpellScript { -public: - spell_ahn_kahet_swarmer_aura() : SpellScriptLoader("spell_ahn_kahet_swarmer_aura") { } + PrepareSpellScript(spell_ahn_kahet_swarmer_aura) - class spell_ahn_kahet_swarmer_aura_SpellScript : public SpellScript + void CountTargets(std::list& targets) { - PrepareSpellScript(spell_ahn_kahet_swarmer_aura_SpellScript) + _targetCount = static_cast(targets.size()); + } - void CountTargets(std::list& targets) + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + if (_targetCount) { - _targetCount = static_cast(targets.size()); - } - - void HandleDummy(SpellEffIndex /*effIndex*/) - { - Unit* caster = GetCaster(); - if (_targetCount) + if (Aura *aur = caster->GetAura(SPELL_SWARM)) { + aur->SetStackAmount(static_cast(_targetCount)); + } + else if (_targetCount) + { + // TODO: move spell id to enum + caster->CastCustomSpell(SPELL_SWARM, SPELLVALUE_AURA_STACK, _targetCount, caster, true); if (Aura *aur = caster->GetAura(SPELL_SWARM)) { aur->SetStackAmount(static_cast(_targetCount)); } - else if (_targetCount) - { - // TODO: move spell id to enum - caster->CastCustomSpell(SPELL_SWARM, SPELLVALUE_AURA_STACK, _targetCount, caster, true); - if (Aura *aur = caster->GetAura(SPELL_SWARM)) - { - aur->SetStackAmount(static_cast(_targetCount)); - } - } - } - else - { - caster->RemoveAurasDueToSpell(SPELL_SWARM); } } - - uint32 _targetCount; - - void Register() override + else { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ahn_kahet_swarmer_aura_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); - OnEffectHitTarget += SpellEffectFn(spell_ahn_kahet_swarmer_aura_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + caster->RemoveAurasDueToSpell(SPELL_SWARM); } - }; + } - SpellScript* GetSpellScript() const override + uint32 _targetCount; + + void Register() override { - return new spell_ahn_kahet_swarmer_aura_SpellScript(); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ahn_kahet_swarmer_aura::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnEffectHitTarget += SpellEffectFn(spell_ahn_kahet_swarmer_aura::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); } }; @@ -417,11 +384,11 @@ class achievement_respect_your_elders : public AchievementCriteriaScript void AddSC_boss_elder_nadox() { // Creatures - new boss_elder_nadox(); - new npc_ahnkahar_nerubian(); + RegisterAhnKahetCreatureAI(boss_elder_nadox); + RegisterAhnKahetCreatureAI(npc_ahnkahar_nerubian); // Spells - new spell_ahn_kahet_swarmer_aura(); + RegisterSpellScript(spell_ahn_kahet_swarmer_aura); // Achievements new achievement_respect_your_elders(); 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 012fb8416..86e71d9e8 100644 --- a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_herald_volazj.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_herald_volazj.cpp @@ -86,380 +86,357 @@ enum Events const std::array InsanitySpells = { SPELL_INSANITY_PHASING_1, SPELL_INSANITY_PHASING_2, SPELL_INSANITY_PHASING_3, SPELL_INSANITY_PHASING_4, SPELL_INSANITY_PHASING_5 }; -class boss_volazj : public CreatureScript +struct boss_volazj : public BossAI { -public: - boss_volazj() : CreatureScript("boss_volazj") { } + boss_volazj(Creature* pCreature) : BossAI(pCreature, DATA_HERALD_VOLAZJ), + insanityTimes(0), + insanityPhase(false) + { } - struct boss_volazjAI : public BossAI + void InitializeAI() override { - boss_volazjAI(Creature* pCreature) : BossAI(pCreature, DATA_HERALD_VOLAZJ), - insanityTimes(0), - insanityPhase(false) + BossAI::InitializeAI(); + // Visible for all players in insanity + me->SetPhaseMask((1 | 16 | 32 | 64 | 128 | 256), true); + } + + void Reset() override + { + _Reset(); + insanityTimes = 0; + insanityPhase = false; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetControlled(false, UNIT_STATE_STUNNED); + ResetPlayersPhaseMask(); + instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); + } + + void EnterCombat(Unit* /*who*/) override + { + _EnterCombat(); + events.ScheduleEvent(EVENT_HERALD_MIND_FLAY, 8000); + events.ScheduleEvent(EVENT_HERALD_SHADOW, 5000); + events.ScheduleEvent(EVENT_HERALD_SHIVER, 15000); + Talk(SAY_AGGRO); + DoCastSelf(SPELL_WHISPER_AGGRO); + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); + me->SetInCombatWithZone(); + } + + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetControlled(false, UNIT_STATE_STUNNED); + ResetPlayersPhaseMask(); + + switch (urand(0, 1)) { + case 0: + { + Talk(SAY_DEATH_1); + DoCastSelf(SPELL_WHISPER_DEATH_1, true); + break; + } + case 1: + { + Talk(SAY_DEATH_2); + DoCastSelf(SPELL_WHISPER_DEATH_2, true); + break; + } } + } - void InitializeAI() override + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) { - BossAI::InitializeAI(); - // Visible for all players in insanity - me->SetPhaseMask((1 | 16 | 32 | 64 | 128 | 256), true); - } - - void Reset() override - { - _Reset(); - insanityTimes = 0; - insanityPhase = false; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetControlled(false, UNIT_STATE_STUNNED); - ResetPlayersPhaseMask(); - instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); - } - - void EnterCombat(Unit* /*who*/) override - { - _EnterCombat(); - events.ScheduleEvent(EVENT_HERALD_MIND_FLAY, 8000); - events.ScheduleEvent(EVENT_HERALD_SHADOW, 5000); - events.ScheduleEvent(EVENT_HERALD_SHIVER, 15000); - Talk(SAY_AGGRO); - DoCastSelf(SPELL_WHISPER_AGGRO); - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); - me->SetInCombatWithZone(); - } - - void JustDied(Unit* /*killer*/) override - { - _JustDied(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetControlled(false, UNIT_STATE_STUNNED); - ResetPlayersPhaseMask(); - - switch (urand(0, 1)) + switch (urand(0, 2)) { case 0: { - Talk(SAY_DEATH_1); - DoCastSelf(SPELL_WHISPER_DEATH_1, true); + Talk(SAY_SLAY_1); + DoCastSelf(SPELL_WHISPER_SLAY_1); break; } case 1: { - Talk(SAY_DEATH_2); - DoCastSelf(SPELL_WHISPER_DEATH_2, true); + Talk(SAY_SLAY_2); + DoCastSelf(SPELL_WHISPER_SLAY_2); + break; + } + case 2: + { + Talk(SAY_SLAY_3); + DoCastSelf(SPELL_WHISPER_SLAY_3); break; } } } + } - void KilledUnit(Unit* victim) override + void SetData(uint32 type, uint32 value) override + { + if (type == DATA_SET_INSANITY_PHASE) { - if (victim->GetTypeId() == TYPEID_PLAYER) - { - switch (urand(0, 2)) - { - case 0: - { - Talk(SAY_SLAY_1); - DoCastSelf(SPELL_WHISPER_SLAY_1); - break; - } - case 1: - { - Talk(SAY_SLAY_2); - DoCastSelf(SPELL_WHISPER_SLAY_2); - break; - } - case 2: - { - Talk(SAY_SLAY_3); - DoCastSelf(SPELL_WHISPER_SLAY_3); - break; - } - } - } + insanityPhase = (value != 0); + } + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override + { + // Do not perform insanity recast if boss is casting Insanity already + if (me->FindCurrentSpellBySpellId(SPELL_INSANITY)) + { + return; } - void SetData(uint32 type, uint32 value) override + // First insanity + if (insanityTimes == 0 && me->HealthBelowPctDamaged(66, damage)) { - if (type == DATA_SET_INSANITY_PHASE) - { - insanityPhase = (value != 0); - } + DoCastSelf(SPELL_INSANITY, false); + ++insanityTimes; + } + // Second insanity + else if (insanityTimes == 1 && me->HealthBelowPctDamaged(33, damage)) + { + me->InterruptNonMeleeSpells(false); + DoCastSelf(SPELL_INSANITY, false); + ++insanityTimes; + } + } + + void UpdateAI(uint32 diff) override + { + //Return since we have no target + if (!UpdateVictim()) + { + return; } - void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override + if (insanityPhase) { - // Do not perform insanity recast if boss is casting Insanity already - if (me->FindCurrentSpellBySpellId(SPELL_INSANITY)) + if (!CheckPhaseMinions()) { return; } - // First insanity - if (insanityTimes == 0 && me->HealthBelowPctDamaged(66, damage)) - { - DoCastSelf(SPELL_INSANITY, false); - ++insanityTimes; - } - // Second insanity - else if (insanityTimes == 1 && me->HealthBelowPctDamaged(33, damage)) - { - me->InterruptNonMeleeSpells(false); - DoCastSelf(SPELL_INSANITY, false); - ++insanityTimes; - } + insanityPhase = false; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetControlled(false, UNIT_STATE_STUNNED); + me->RemoveAurasDueToSpell(INSANITY_VISUAL); } - void UpdateAI(uint32 diff) override + events.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) { - //Return since we have no target - if (!UpdateVictim()) - { - return; - } + return; + } - if (insanityPhase) + while (uint32 const eventId = events.ExecuteEvent()) + { + switch (eventId) { - if (!CheckPhaseMinions()) + case EVENT_HERALD_MIND_FLAY: { - return; + DoCastVictim(SPELL_MIND_FLAY, false); + events.RepeatEvent(20000); + break; } + case EVENT_HERALD_SHADOW: + { + DoCastVictim(SPELL_SHADOW_BOLT_VOLLEY, false); + events.RepeatEvent(5000); + break; + } + case EVENT_HERALD_SHIVER: + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + { + DoCast(pTarget, SPELL_SHIVER, false); + } - insanityPhase = false; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetControlled(false, UNIT_STATE_STUNNED); - me->RemoveAurasDueToSpell(INSANITY_VISUAL); + events.RepeatEvent(15000); + break; + } } - events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) { return; } - - while (uint32 const eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_HERALD_MIND_FLAY: - { - DoCastVictim(SPELL_MIND_FLAY, false); - events.RepeatEvent(20000); - break; - } - case EVENT_HERALD_SHADOW: - { - DoCastVictim(SPELL_SHADOW_BOLT_VOLLEY, false); - events.RepeatEvent(5000); - break; - } - case EVENT_HERALD_SHIVER: - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) - { - DoCast(pTarget, SPELL_SHIVER, false); - } - - events.RepeatEvent(15000); - break; - } - } - - if (me->HasUnitState(UNIT_STATE_CASTING)) - { - return; - } - } - - DoMeleeAttackIfReady(); } - private: - uint8 insanityTimes; - bool insanityPhase; // Indicates if boss enter to insanity phase + DoMeleeAttackIfReady(); + } - uint32 GetPlrInsanityAuraId(uint32 phaseMask) const - { - switch (phaseMask) - { - case 16: - return SPELL_INSANITY_PHASING_1; - case 32: - return SPELL_INSANITY_PHASING_2; - case 64: - return SPELL_INSANITY_PHASING_3; - case 128: - return SPELL_INSANITY_PHASING_4; - case 256: - return SPELL_INSANITY_PHASING_5; - } +private: + uint8 insanityTimes; + bool insanityPhase; // Indicates if boss enter to insanity phase - return 0; - } - - void ResetPlayersPhaseMask() - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - for (auto const& i : players) - { - if (Player* pPlayer = i.GetSource()) - { - if (uint32 const insanityAura = GetPlrInsanityAuraId(pPlayer->GetPhaseMask())) - { - pPlayer->RemoveAurasDueToSpell(insanityAura); - } - } - } - } - - bool CheckPhaseMinions() - { - summons.RemoveNotExisting(); - if (summons.empty()) - { - ResetPlayersPhaseMask(); - return true; - } - - uint32 phase = 1; - for (ObjectGuid const& summonGUID : summons) - { - if (Creature* summon = ObjectAccessor::GetCreature(*me, summonGUID)) - { - phase |= summon->GetPhaseMask(); - } - } - - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - for (auto const& i : players) - { - Player* pPlayer = i.GetSource(); - if (pPlayer && !(pPlayer->GetPhaseMask() & phase)) - { - pPlayer->RemoveAurasDueToSpell(GetPlrInsanityAuraId(pPlayer->GetPhaseMask())); - } - } - - return false; - } - }; - - CreatureAI* GetAI(Creature* creature) const override + uint32 GetPlrInsanityAuraId(uint32 phaseMask) const { - return GetAhnKahetAI(creature); + switch (phaseMask) + { + case 16: + return SPELL_INSANITY_PHASING_1; + case 32: + return SPELL_INSANITY_PHASING_2; + case 64: + return SPELL_INSANITY_PHASING_3; + case 128: + return SPELL_INSANITY_PHASING_4; + case 256: + return SPELL_INSANITY_PHASING_5; + } + + return 0; + } + + void ResetPlayersPhaseMask() + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + for (auto const& i : players) + { + if (Player* pPlayer = i.GetSource()) + { + if (uint32 const insanityAura = GetPlrInsanityAuraId(pPlayer->GetPhaseMask())) + { + pPlayer->RemoveAurasDueToSpell(insanityAura); + } + } + } + } + + bool CheckPhaseMinions() + { + summons.RemoveNotExisting(); + if (summons.empty()) + { + ResetPlayersPhaseMask(); + return true; + } + + uint32 phase = 1; + for (ObjectGuid const& summonGUID : summons) + { + if (Creature* summon = ObjectAccessor::GetCreature(*me, summonGUID)) + { + phase |= summon->GetPhaseMask(); + } + } + + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + for (auto const& i : players) + { + Player* pPlayer = i.GetSource(); + if (pPlayer && !(pPlayer->GetPhaseMask() & phase)) + { + pPlayer->RemoveAurasDueToSpell(GetPlrInsanityAuraId(pPlayer->GetPhaseMask())); + } + } + + return false; } }; // 57496 Insanity -class spell_herald_volzaj_insanity : public SpellScriptLoader +class spell_herald_volzaj_insanity : public SpellScript { -public: - spell_herald_volzaj_insanity() : SpellScriptLoader("spell_herald_volzaj_insanity") { } + PrepareSpellScript(spell_herald_volzaj_insanity); - class spell_herald_volzaj_insanity_SpellScript : public SpellScript + bool Load() override { return GetCaster()->GetTypeId() == TYPEID_UNIT; } + + void HandleDummyEffect(std::list& targets) { - PrepareSpellScript(spell_herald_volzaj_insanity_SpellScript); - - bool Load() override { return GetCaster()->GetTypeId() == TYPEID_UNIT; } - - void HandleDummyEffect(std::list& targets) + Unit* caster = GetCaster(); + if (!caster) { - Unit* caster = GetCaster(); - if (!caster) + targets.clear(); + return; + } + + if (!targets.empty()) + { + targets.remove_if([this](WorldObject* targetObj) -> bool { - targets.clear(); - return; + return !targetObj || targetObj->GetTypeId() != TYPEID_PLAYER || !targetObj->ToPlayer()->IsInCombatWith(GetCaster()) || + targetObj->GetDistance(GetCaster()) >= (MAX_VISIBILITY_DISTANCE * 2); + }); + } + + if (targets.empty()) + { + return; + } + + // Start channel visual and set self as unnattackable + caster->ToCreature()->AI()->Talk(SAY_INSANITY); + caster->CastSpell(caster, SPELL_WHISPER_INSANITY, true); + caster->RemoveAllAuras(); + caster->CastSpell(caster, INSANITY_VISUAL, true); + caster->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + caster->SetControlled(true, UNIT_STATE_STUNNED); + + // Handle phase effect + uint32 insanityCounter = 0; + std::list::const_iterator itr = targets.begin(); + while (itr != targets.end() && insanityCounter < MAX_INSANITY_TARGETS) + { + WorldObject* targetObj = *itr; + if (!targetObj) + { + continue; } - if (!targets.empty()) + Player* plrTarget = targetObj->ToPlayer(); + // This should never happen, spell has attribute SPELL_ATTR3_ONLY_TARGET_PLAYERS + if (!plrTarget) { - targets.remove_if([this](WorldObject* targetObj) -> bool - { - return !targetObj || targetObj->GetTypeId() != TYPEID_PLAYER || !targetObj->ToPlayer()->IsInCombatWith(GetCaster()) || - targetObj->GetDistance(GetCaster()) >= (MAX_VISIBILITY_DISTANCE * 2); - }); + continue; } - if (targets.empty()) - { - return; - } + // phase mask + plrTarget->CastSpell(plrTarget, InsanitySpells.at(insanityCounter), true); - // Start channel visual and set self as unnattackable - caster->ToCreature()->AI()->Talk(SAY_INSANITY); - caster->CastSpell(caster, SPELL_WHISPER_INSANITY, true); - caster->RemoveAllAuras(); - caster->CastSpell(caster, INSANITY_VISUAL, true); - caster->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - caster->SetControlled(true, UNIT_STATE_STUNNED); - - // Handle phase effect - uint32 insanityCounter = 0; - std::list::const_iterator itr = targets.begin(); - while (itr != targets.end() && insanityCounter < MAX_INSANITY_TARGETS) + // Summon clone + for (std::list::const_iterator itr2 = targets.begin(); itr2 != targets.end(); ++itr2) { - WorldObject* targetObj = *itr; - if (!targetObj) + // Should not make clone of current player target + Player const* plrClone = *itr2 ? (*itr2)->ToPlayer() : nullptr; + if (!plrClone || plrClone == plrTarget) { continue; } - Player* plrTarget = targetObj->ToPlayer(); - // This should never happen, spell has attribute SPELL_ATTR3_ONLY_TARGET_PLAYERS - if (!plrTarget) + if (Unit* summon = caster->SummonCreature(NPC_TWISTED_VISAGE, plrClone->GetPosition(), TEMPSUMMON_CORPSE_DESPAWN, 0)) { - continue; + summon->AddThreat(plrTarget, 0.0f); + summon->SetInCombatWith(plrTarget); + plrTarget->SetInCombatWith(summon); + + plrTarget->CastSpell(summon, SPELL_CLONE_PLAYER, true); + summon->SetPhaseMask(1 | (1 << (4 + insanityCounter)), true); + summon->SetUInt32Value(UNIT_FIELD_MINDAMAGE, plrClone->GetUInt32Value(UNIT_FIELD_MINDAMAGE)); + summon->SetUInt32Value(UNIT_FIELD_MAXDAMAGE, plrClone->GetUInt32Value(UNIT_FIELD_MAXDAMAGE)); } - - // phase mask - plrTarget->CastSpell(plrTarget, InsanitySpells.at(insanityCounter), true); - - // Summon clone - for (std::list::const_iterator itr2 = targets.begin(); itr2 != targets.end(); ++itr2) - { - // Should not make clone of current player target - Player const* plrClone = *itr2 ? (*itr2)->ToPlayer() : nullptr; - if (!plrClone || plrClone == plrTarget) - { - continue; - } - - if (Unit* summon = caster->SummonCreature(NPC_TWISTED_VISAGE, plrClone->GetPosition(), TEMPSUMMON_CORPSE_DESPAWN, 0)) - { - summon->AddThreat(plrTarget, 0.0f); - summon->SetInCombatWith(plrTarget); - plrTarget->SetInCombatWith(summon); - - plrTarget->CastSpell(summon, SPELL_CLONE_PLAYER, true); - summon->SetPhaseMask(1 | (1 << (4 + insanityCounter)), true); - summon->SetUInt32Value(UNIT_FIELD_MINDAMAGE, plrClone->GetUInt32Value(UNIT_FIELD_MINDAMAGE)); - summon->SetUInt32Value(UNIT_FIELD_MAXDAMAGE, plrClone->GetUInt32Value(UNIT_FIELD_MAXDAMAGE)); - } - } - - ++insanityCounter; - ++itr; } - } - void HandleAfterCast() - { - GetCaster()->ToCreature()->AI()->SetData(DATA_SET_INSANITY_PHASE, 1); + ++insanityCounter; + ++itr; } + } - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_herald_volzaj_insanity_SpellScript::HandleDummyEffect, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - AfterCast += SpellCastFn(spell_herald_volzaj_insanity_SpellScript::HandleAfterCast); - } - }; - - SpellScript* GetSpellScript() const override + void HandleAfterCast() { - return new spell_herald_volzaj_insanity_SpellScript(); + GetCaster()->ToCreature()->AI()->SetData(DATA_SET_INSANITY_PHASE, 1); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_herald_volzaj_insanity::HandleDummyEffect, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + AfterCast += SpellCastFn(spell_herald_volzaj_insanity::HandleAfterCast); } }; @@ -470,70 +447,59 @@ public: // 60295 Volazj Whisper: Slay 03 // 60296 Volazj Whisper: Death 01 // 60297 Volazj Whisper: Death 02 -class spell_volazj_whisper : public SpellScriptLoader +class spell_volazj_whisper : public SpellScript { -public: - spell_volazj_whisper() : SpellScriptLoader("spell_volazj_whisper") { } + PrepareSpellScript(spell_volazj_whisper); - class spell_volazj_whisper_SpellScript : public SpellScript + bool Validate(SpellInfo const* /*spell*/) override { - PrepareSpellScript(spell_volazj_whisper_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override + return ValidateSpellInfo( { - return ValidateSpellInfo( - { - SPELL_WHISPER_AGGRO, - SPELL_WHISPER_INSANITY, - SPELL_WHISPER_SLAY_1, - SPELL_WHISPER_SLAY_2, - SPELL_WHISPER_SLAY_3, - SPELL_WHISPER_DEATH_1, - SPELL_WHISPER_DEATH_2 - }); - } + SPELL_WHISPER_AGGRO, + SPELL_WHISPER_INSANITY, + SPELL_WHISPER_SLAY_1, + SPELL_WHISPER_SLAY_2, + SPELL_WHISPER_SLAY_3, + SPELL_WHISPER_DEATH_1, + SPELL_WHISPER_DEATH_2 + }); + } - bool Load() override { return GetCaster()->GetTypeId() == TYPEID_UNIT; } + bool Load() override { return GetCaster()->GetTypeId() == TYPEID_UNIT; } - void HandleScriptEffect(SpellEffIndex /* effIndex */) - { - Unit* target = GetHitPlayer(); - Creature* caster = GetCaster()->ToCreature(); - if (!target || !caster) - { - return; - } - - uint32 text = 0; - switch (GetSpellInfo()->Id) - { - case SPELL_WHISPER_AGGRO: text = WHISPER_AGGRO; break; - case SPELL_WHISPER_INSANITY: text = WHISPER_INSANITY; break; - case SPELL_WHISPER_SLAY_1: text = WHISPER_SLAY_1; break; - case SPELL_WHISPER_SLAY_2: text = WHISPER_SLAY_2; break; - case SPELL_WHISPER_SLAY_3: text = WHISPER_SLAY_3; break; - case SPELL_WHISPER_DEATH_1: text = WHISPER_DEATH_1; break; - case SPELL_WHISPER_DEATH_2: text = WHISPER_DEATH_2; break; - default: return; - } - caster->AI()->Talk(text, target); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_volazj_whisper_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override + void HandleScriptEffect(SpellEffIndex /* effIndex */) { - return new spell_volazj_whisper_SpellScript(); + Unit* target = GetHitPlayer(); + Creature* caster = GetCaster()->ToCreature(); + if (!target || !caster) + { + return; + } + + uint32 text = 0; + switch (GetSpellInfo()->Id) + { + case SPELL_WHISPER_AGGRO: text = WHISPER_AGGRO; break; + case SPELL_WHISPER_INSANITY: text = WHISPER_INSANITY; break; + case SPELL_WHISPER_SLAY_1: text = WHISPER_SLAY_1; break; + case SPELL_WHISPER_SLAY_2: text = WHISPER_SLAY_2; break; + case SPELL_WHISPER_SLAY_3: text = WHISPER_SLAY_3; break; + case SPELL_WHISPER_DEATH_1: text = WHISPER_DEATH_1; break; + case SPELL_WHISPER_DEATH_2: text = WHISPER_DEATH_2; break; + default: return; + } + caster->AI()->Talk(text, target); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_volazj_whisper::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; void AddSC_boss_volazj() { - new boss_volazj(); - new spell_herald_volzaj_insanity(); - new spell_volazj_whisper(); + RegisterAhnKahetCreatureAI(boss_volazj); + RegisterSpellScript(spell_herald_volzaj_insanity); + RegisterSpellScript(spell_volazj_whisper); } diff --git a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_jedoga_shadowseeker.cpp b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_jedoga_shadowseeker.cpp index 6f917563c..132b04717 100644 --- a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_jedoga_shadowseeker.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_jedoga_shadowseeker.cpp @@ -150,607 +150,562 @@ const Position VolunteerSpotPositions[MAX_COMBAT_INITIATES][2] = { { 404.0797f, -783.829f, -31.59497f }, { 367.8631f, -722.5212f, -16.17974f } } }; -class boss_jedoga_shadowseeker : public CreatureScript +struct boss_jedoga_shadowseeker : public BossAI { -public: - boss_jedoga_shadowseeker() : CreatureScript("boss_jedoga_shadowseeker") { } + boss_jedoga_shadowseeker(Creature* pCreature) : BossAI(pCreature, DATA_JEDOGA_SHADOWSEEKER), + sayPreachTimer(120000), + combatSummonsSummoned(false), + ritualTriggered(false), + volunteerWork(true) + { } - struct boss_jedoga_shadowseekerAI : public BossAI + // Disabled events + void MoveInLineOfSight(Unit* /*who*/) override {} + + void Reset() override { - boss_jedoga_shadowseekerAI(Creature* pCreature) : BossAI(pCreature, DATA_JEDOGA_SHADOWSEEKER), - sayPreachTimer(120000), - combatSummonsSummoned(false), - ritualTriggered(false), - volunteerWork(true) + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_IMMUNE_TO_PC); + me->AddUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD); + me->SetDisableGravity(true); + me->SetHover(true); + me->GetMotionMaster()->MovePoint(POINT_INITIAL, JedogaPosition[0], false); + + _Reset(); + events.SetPhase(PHASE_NORMAL); + + DespawnOOCSummons(); + std::list tempOOCSummons; + me->SummonCreatureGroup(SUMMON_GROUP_OOC, &tempOOCSummons); + if (!tempOOCSummons.empty()) { - } - - // Disabled events - void MoveInLineOfSight(Unit* /*who*/) override {} - - void Reset() override - { - me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_IMMUNE_TO_PC); - me->AddUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD); - me->SetDisableGravity(true); - me->SetHover(true); - me->GetMotionMaster()->MovePoint(POINT_INITIAL, JedogaPosition[0], false); - - _Reset(); - events.SetPhase(PHASE_NORMAL); - - DespawnOOCSummons(); - std::list tempOOCSummons; - me->SummonCreatureGroup(SUMMON_GROUP_OOC, &tempOOCSummons); - if (!tempOOCSummons.empty()) + for (TempSummon* summon : tempOOCSummons) { - for (TempSummon* summon : tempOOCSummons) + if (summon) { - if (summon) - { - summon->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); - summon->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); - summon->RemoveAurasDueToSpell(SPELL_WHITE_SPHERE); - summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - summon->SetStandState(UNIT_STAND_STATE_KNEEL); - oocSummons.push_back(summon->GetGUID()); - } + summon->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); + summon->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); + summon->RemoveAurasDueToSpell(SPELL_WHITE_SPHERE); + summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + summon->SetStandState(UNIT_STAND_STATE_KNEEL); + oocSummons.push_back(summon->GetGUID()); } } + } - tempOOCSummons.clear(); + tempOOCSummons.clear(); - me->SummonCreatureGroup(SUMMON_GROUP_OOC_TRIGGERS, &tempOOCSummons); - if (!tempOOCSummons.empty()) + me->SummonCreatureGroup(SUMMON_GROUP_OOC_TRIGGERS, &tempOOCSummons); + if (!tempOOCSummons.empty()) + { + for (TempSummon* trigger : tempOOCSummons) { - for (TempSummon* trigger : tempOOCSummons) + if (trigger) { - if (trigger) - { - oocTriggers.push_back(trigger->GetGUID()); - } + oocTriggers.push_back(trigger->GetGUID()); } } - - sacraficeTarget_GUID.Clear(); - sayPreachTimer = 120000; - ritualTriggered = false; - volunteerWork = true; - combatSummonsSummoned = false; } - void JustSummoned(Creature* summon) override - { - if (summon->GetEntry() == NPC_JEDOGA_CONTROLLER) - { - summons.Summon(summon); - } - } + sacraficeTarget_GUID.Clear(); + sayPreachTimer = 120000; + ritualTriggered = false; + volunteerWork = true; + combatSummonsSummoned = false; + } - void SummonedCreatureDies(Creature* summon, Unit* killer) override + void JustSummoned(Creature* summon) override + { + if (summon->GetEntry() == NPC_JEDOGA_CONTROLLER) { - switch (summon->GetEntry()) + summons.Summon(summon); + } + } + + void SummonedCreatureDies(Creature* summon, Unit* killer) override + { + switch (summon->GetEntry()) + { + case NPC_TWILIGHT_INITIATE: { - case NPC_TWILIGHT_INITIATE: + GuidList::iterator itr = std::find(oocSummons.begin(), oocSummons.end(), summon->GetGUID()); + if (itr == oocSummons.end()) { - GuidList::iterator itr = std::find(oocSummons.begin(), oocSummons.end(), summon->GetGUID()); - if (itr == oocSummons.end()) - { - break; - } - - oocSummons.erase(itr); - if (!oocSummons.empty()) - { - break; - } - - DespawnOOCSummons(); - DoCastSelf(SPELL_HOVER_FALL); - me->GetMotionMaster()->MoveIdle(); - me->GetMotionMaster()->MovePoint(POINT_DOWN, JedogaPosition[1], false); - - if (!combatSummonsSummoned) - { - summons.DespawnEntry(NPC_TWILIGHT_VOLUNTEER); - for (uint8 i = 0; i < MAX_COMBAT_INITIATES; ++i) - { - if (TempSummon* summon = me->SummonCreature(NPC_TWILIGHT_VOLUNTEER, VolunteerSpotPositions[i][0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000)) - { - summon->GetMotionMaster()->MovePoint(POINT_INITIAL, VolunteerSpotPositions[i][1]); - summon->SetReactState(REACT_PASSIVE); - summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC ); - summons.Summon(summon); - } - } - combatSummonsSummoned = true; - } - break; } - case NPC_TWILIGHT_VOLUNTEER: - { - if (sacraficeTarget_GUID && summon->GetGUID() != sacraficeTarget_GUID) - { - break; - } - if (killer != me && killer->GetGUID() != sacraficeTarget_GUID) + oocSummons.erase(itr); + if (!oocSummons.empty()) + { + break; + } + + DespawnOOCSummons(); + DoCastSelf(SPELL_HOVER_FALL); + me->GetMotionMaster()->MoveIdle(); + me->GetMotionMaster()->MovePoint(POINT_DOWN, JedogaPosition[1], false); + + if (!combatSummonsSummoned) + { + summons.DespawnEntry(NPC_TWILIGHT_VOLUNTEER); + for (uint8 i = 0; i < MAX_COMBAT_INITIATES; ++i) + { + if (TempSummon* summon = me->SummonCreature(NPC_TWILIGHT_VOLUNTEER, VolunteerSpotPositions[i][0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000)) + { + summon->GetMotionMaster()->MovePoint(POINT_INITIAL, VolunteerSpotPositions[i][1]); + summon->SetReactState(REACT_PASSIVE); + summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC ); + summons.Summon(summon); + } + } + combatSummonsSummoned = true; + } + + break; + } + case NPC_TWILIGHT_VOLUNTEER: + { + if (sacraficeTarget_GUID && summon->GetGUID() != sacraficeTarget_GUID) + { + break; + } + + if (killer != me && killer->GetGUID() != sacraficeTarget_GUID) + { + volunteerWork = false; + } + else + { + DoCastSelf(SPELL_GIFT_OF_THE_HERALD, true); + } + events.ScheduleEvent(EVENT_JEDOGA_MOVE_DOWN, 1000, 0, PHASE_RITUAL); + break; + } + } + + summons.Despawn(summon); + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*school*/) override + { + if (!ritualTriggered && me->HealthBelowPctDamaged(55, damage) && events.IsInPhase(PHASE_NORMAL)) + { + SetCombatMovement(false); + me->InterruptNonMeleeSpells(false); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + + events.SetPhase(PHASE_RITUAL); + events.ScheduleEvent(EVENT_JEDOGA_PREPARE_RITUAL, 1000, 0, PHASE_RITUAL); + ritualTriggered = true; + return; + } + + if (events.IsInPhase(PHASE_RITUAL)) + { + damage = 0; + } + } + + void DoAction(int32 action) override + { + if (action == ACTION_SACRAFICE) + { + if (Creature* target = ObjectAccessor::GetCreature(*me, sacraficeTarget_GUID)) + { + Unit::Kill(me, target); + } + } + } + + void EnterCombat(Unit* /*who*/) override + { + _EnterCombat(); + Talk(SAY_AGGRO); + ReschedulleCombatEvents(); + } + + void KilledUnit(Unit* who) override + { + if (who->GetTypeId() != TYPEID_PLAYER) + { + return; + } + + Talk(SAY_SLAY); + } + + void JustDied(Unit* /*Killer*/) override + { + _JustDied(); + DespawnOOCSummons(); + Talk(SAY_DEATH); + } + + void MovementInform(uint32 type, uint32 pointId) override + { + if (!(type == POINT_MOTION_TYPE || type == EFFECT_MOTION_TYPE)) + { + return; + } + + switch (pointId) + { + case POINT_DOWN: + { + me->ClearUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD); + ReschedulleCombatEvents(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_AGGRESSIVE); + + me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); + me->RemoveAurasDueToSpell(SPELL_LIGHTNING_BOLTS); + me->RemoveAurasDueToSpell(SPELL_HOVER_FALL); + SetCombatMovement(true); + + me->SetDisableGravity(false); + me->SetHover(false); + + me->SetInCombatWithZone(); + if (Unit* victim = me->GetVictim()) + { + me->StopMoving(); + AttackStart(victim); + } + break; + } + case POINT_UP: + { + me->SetFacingTo(5.66f); + if (!summons.empty()) + { + sacraficeTarget_GUID = Acore::Containers::SelectRandomContainerElement(summons); + if (Creature* volunteer = ObjectAccessor::GetCreature(*me, sacraficeTarget_GUID)) + { + Talk(SAY_SACRIFICE_1); + sacraficeTarget_GUID = volunteer->GetGUID(); + volunteer->AI()->DoAction(ACTION_RITUAL_BEGIN); + } + // Something failed, let players continue but do not grant achievement + else { volunteerWork = false; - } - else - { - DoCastSelf(SPELL_GIFT_OF_THE_HERALD, true); - } - events.ScheduleEvent(EVENT_JEDOGA_MOVE_DOWN, 1000, 0, PHASE_RITUAL); - break; - } - } - - summons.Despawn(summon); - } - - void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*school*/) override - { - if (!ritualTriggered && me->HealthBelowPctDamaged(55, damage) && events.IsInPhase(PHASE_NORMAL)) - { - SetCombatMovement(false); - me->InterruptNonMeleeSpells(false); - me->AttackStop(); - me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - - events.SetPhase(PHASE_RITUAL); - events.ScheduleEvent(EVENT_JEDOGA_PREPARE_RITUAL, 1000, 0, PHASE_RITUAL); - ritualTriggered = true; - return; - } - - if (events.IsInPhase(PHASE_RITUAL)) - { - damage = 0; - } - } - - void DoAction(int32 action) override - { - if (action == ACTION_SACRAFICE) - { - if (Creature* target = ObjectAccessor::GetCreature(*me, sacraficeTarget_GUID)) - { - Unit::Kill(me, target); - } - } - } - - void EnterCombat(Unit* /*who*/) override - { - _EnterCombat(); - Talk(SAY_AGGRO); - ReschedulleCombatEvents(); - } - - void KilledUnit(Unit* who) override - { - if (who->GetTypeId() != TYPEID_PLAYER) - { - return; - } - - Talk(SAY_SLAY); - } - - void JustDied(Unit* /*Killer*/) override - { - _JustDied(); - DespawnOOCSummons(); - Talk(SAY_DEATH); - } - - void MovementInform(uint32 type, uint32 pointId) override - { - if (!(type == POINT_MOTION_TYPE || type == EFFECT_MOTION_TYPE)) - { - return; - } - - switch (pointId) - { - case POINT_DOWN: - { - me->ClearUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD); - ReschedulleCombatEvents(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_AGGRESSIVE); - - me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); - me->RemoveAurasDueToSpell(SPELL_LIGHTNING_BOLTS); - me->RemoveAurasDueToSpell(SPELL_HOVER_FALL); - SetCombatMovement(true); - - me->SetDisableGravity(false); - me->SetHover(false); - - me->SetInCombatWithZone(); - if (Unit* victim = me->GetVictim()) - { - me->StopMoving(); - AttackStart(victim); - } - break; - } - case POINT_UP: - { - me->SetFacingTo(5.66f); - if (!summons.empty()) - { - sacraficeTarget_GUID = Acore::Containers::SelectRandomContainerElement(summons); - if (Creature* volunteer = ObjectAccessor::GetCreature(*me, sacraficeTarget_GUID)) - { - Talk(SAY_SACRIFICE_1); - sacraficeTarget_GUID = volunteer->GetGUID(); - volunteer->AI()->DoAction(ACTION_RITUAL_BEGIN); - } - // Something failed, let players continue but do not grant achievement - else - { - volunteerWork = false; - me->GetMotionMaster()->Clear(); - DoCastSelf(SPELL_HOVER_FALL); - me->GetMotionMaster()->MovePoint(POINT_DOWN, JedogaPosition[1], false); - } - } - break; - } - case POINT_RITUAL: - { - me->SetFacingTo(5.66f); - DoCastSelf(SPELL_HOVER_FALL); - events.ScheduleEvent(EVENT_JEDOGA_MOVE_UP, 1000, 0, PHASE_RITUAL); - break; - } - case POINT_INITIAL: - { - me->SetFacingTo(5.66f); - DoCastSelf(SPELL_SPHERE_VISUAL, true); - DoCastSelf(SPELL_LIGHTNING_BOLTS, true); - if (!oocTriggers.empty()) - { - for (ObjectGuid const& guid : oocTriggers) - { - if (Creature* trigger = ObjectAccessor::GetCreature(*me, guid)) - { - trigger->CastSpell(nullptr, SPELL_BEAM_VISUAL_JEDOGA); - } - } - } - break; - } - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - { - if (instance->GetBossState(DATA_PRINCE_TALDARAM) == DONE) - { - if (sayPreachTimer <= diff) - { - Talk(SAY_PREACHING); - sayPreachTimer = 120000; // 2 min - } - else - { - sayPreachTimer -= diff; - } - } - return; - } - - events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - { - return; - } - - while (uint32 const eventId = events.ExecuteEvent()) - { - switch (eventId) - { - // Normal phase - case EVENT_JEDOGA_CYCLONE: - { - DoCastSelf(DUNGEON_MODE(SPELL_CYCLONE_STRIKE, SPELL_CYCLONE_STRIKE_H), false); - events.RepeatEvent(urand(10000, 14000)); - break; - } - case EVENT_JEDOGA_LIGHTNING_BOLT: - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoCast(pTarget, DUNGEON_MODE(SPELL_LIGHTNING_BOLT, SPELL_LIGHTNING_BOLT_H), false); - } - events.RepeatEvent(urand(11000, 15000)); - break; - } - case EVENT_JEDOGA_THUNDERSHOCK: - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoCast(pTarget, DUNGEON_MODE(SPELL_THUNDERSHOCK, SPELL_THUNDERSHOCK_H), false); - } - - events.RepeatEvent(urand(16000, 22000)); - break; - } - // Ritual phase - case EVENT_JEDOGA_PREPARE_RITUAL: - { - me->GetMotionMaster()->Clear(true); - me->GetMotionMaster()->MovePoint(POINT_RITUAL, JedogaPosition[1]); - break; - } - case EVENT_JEDOGA_MOVE_UP: - { - me->GetMotionMaster()->Clear(true); - me->SetDisableGravity(true); - me->SetHover(true); - me->GetMotionMaster()->MoveTakeoff(POINT_UP, JedogaPosition[0], 7.0f); - break; - } - case EVENT_JEDOGA_MOVE_DOWN: - { - summons.DespawnEntry(NPC_JEDOGA_CONTROLLER); - DoCastSelf(SPELL_HOVER_FALL); me->GetMotionMaster()->Clear(); + DoCastSelf(SPELL_HOVER_FALL); me->GetMotionMaster()->MovePoint(POINT_DOWN, JedogaPosition[1], false); - break; } } + break; } - - DoMeleeAttackIfReady(); - } - - uint32 GetData(uint32 type) const override - { - if (type == DATA_VOLUNTEER_WORK) + case POINT_RITUAL: { - return volunteerWork ? 1 : 0; + me->SetFacingTo(5.66f); + DoCastSelf(SPELL_HOVER_FALL); + events.ScheduleEvent(EVENT_JEDOGA_MOVE_UP, 1000, 0, PHASE_RITUAL); + break; } - - return 0; - } - - private: - GuidList oocSummons; - GuidList oocTriggers; - ObjectGuid sacraficeTarget_GUID; - uint32 sayPreachTimer; - bool combatSummonsSummoned; - bool ritualTriggered; - bool volunteerWork; // true = success, false = failed - - void ReschedulleCombatEvents() - { - events.SetPhase(PHASE_NORMAL); - events.RescheduleEvent(EVENT_JEDOGA_CYCLONE, 3000, 0, PHASE_NORMAL); - events.RescheduleEvent(EVENT_JEDOGA_LIGHTNING_BOLT, 7000, 0, PHASE_NORMAL); - events.RescheduleEvent(EVENT_JEDOGA_THUNDERSHOCK, 12000, 0, PHASE_NORMAL); - } - - void DespawnOOCSummons() - { - if (!oocTriggers.empty()) + case POINT_INITIAL: { - for (ObjectGuid const& guid : oocTriggers) + me->SetFacingTo(5.66f); + DoCastSelf(SPELL_SPHERE_VISUAL, true); + DoCastSelf(SPELL_LIGHTNING_BOLTS, true); + if (!oocTriggers.empty()) { - if (Creature* summon = ObjectAccessor::GetCreature(*me, guid)) + for (ObjectGuid const& guid : oocTriggers) { - summon->DespawnOrUnsummon(); + if (Creature* trigger = ObjectAccessor::GetCreature(*me, guid)) + { + trigger->CastSpell(nullptr, SPELL_BEAM_VISUAL_JEDOGA); + } } } - oocTriggers.clear(); - } - - if (!oocSummons.empty()) - { - for (ObjectGuid const& guid : oocSummons) - { - if (Creature* summon = ObjectAccessor::GetCreature(*me, guid)) - { - summon->DespawnOrUnsummon(); - } - } - oocSummons.clear(); + break; } } - }; + } - CreatureAI* GetAI(Creature* creature) const override + void UpdateAI(uint32 diff) override { - return GetAhnKahetAI(creature); + if (!UpdateVictim()) + { + if (instance->GetBossState(DATA_PRINCE_TALDARAM) == DONE) + { + if (sayPreachTimer <= diff) + { + Talk(SAY_PREACHING); + sayPreachTimer = 120000; // 2 min + } + else + { + sayPreachTimer -= diff; + } + } + return; + } + + events.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) + { + return; + } + + while (uint32 const eventId = events.ExecuteEvent()) + { + switch (eventId) + { + // Normal phase + case EVENT_JEDOGA_CYCLONE: + { + DoCastSelf(DUNGEON_MODE(SPELL_CYCLONE_STRIKE, SPELL_CYCLONE_STRIKE_H), false); + events.RepeatEvent(urand(10000, 14000)); + break; + } + case EVENT_JEDOGA_LIGHTNING_BOLT: + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoCast(pTarget, DUNGEON_MODE(SPELL_LIGHTNING_BOLT, SPELL_LIGHTNING_BOLT_H), false); + } + events.RepeatEvent(urand(11000, 15000)); + break; + } + case EVENT_JEDOGA_THUNDERSHOCK: + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoCast(pTarget, DUNGEON_MODE(SPELL_THUNDERSHOCK, SPELL_THUNDERSHOCK_H), false); + } + + events.RepeatEvent(urand(16000, 22000)); + break; + } + // Ritual phase + case EVENT_JEDOGA_PREPARE_RITUAL: + { + me->GetMotionMaster()->Clear(true); + me->GetMotionMaster()->MovePoint(POINT_RITUAL, JedogaPosition[1]); + break; + } + case EVENT_JEDOGA_MOVE_UP: + { + me->GetMotionMaster()->Clear(true); + me->SetDisableGravity(true); + me->SetHover(true); + me->GetMotionMaster()->MoveTakeoff(POINT_UP, JedogaPosition[0], 7.0f); + break; + } + case EVENT_JEDOGA_MOVE_DOWN: + { + summons.DespawnEntry(NPC_JEDOGA_CONTROLLER); + DoCastSelf(SPELL_HOVER_FALL); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(POINT_DOWN, JedogaPosition[1], false); + break; + } + } + } + + DoMeleeAttackIfReady(); + } + + uint32 GetData(uint32 type) const override + { + if (type == DATA_VOLUNTEER_WORK) + { + return volunteerWork ? 1 : 0; + } + + return 0; + } + +private: + GuidList oocSummons; + GuidList oocTriggers; + ObjectGuid sacraficeTarget_GUID; + uint32 sayPreachTimer; + bool combatSummonsSummoned; + bool ritualTriggered; + bool volunteerWork; // true = success, false = failed + + void ReschedulleCombatEvents() + { + events.SetPhase(PHASE_NORMAL); + events.RescheduleEvent(EVENT_JEDOGA_CYCLONE, 3000, 0, PHASE_NORMAL); + events.RescheduleEvent(EVENT_JEDOGA_LIGHTNING_BOLT, 7000, 0, PHASE_NORMAL); + events.RescheduleEvent(EVENT_JEDOGA_THUNDERSHOCK, 12000, 0, PHASE_NORMAL); + } + + void DespawnOOCSummons() + { + if (!oocTriggers.empty()) + { + for (ObjectGuid const& guid : oocTriggers) + { + if (Creature* summon = ObjectAccessor::GetCreature(*me, guid)) + { + summon->DespawnOrUnsummon(); + } + } + oocTriggers.clear(); + } + + if (!oocSummons.empty()) + { + for (ObjectGuid const& guid : oocSummons) + { + if (Creature* summon = ObjectAccessor::GetCreature(*me, guid)) + { + summon->DespawnOrUnsummon(); + } + } + oocSummons.clear(); + } } }; -class npc_twilight_volunteer : public CreatureScript +struct npc_twilight_volunteer : public ScriptedAI { -public: - npc_twilight_volunteer() : CreatureScript("npc_twilight_volunteer") { } - - struct npc_twilight_volunteerAI : public ScriptedAI + npc_twilight_volunteer(Creature* pCreature) : ScriptedAI(pCreature), + pInstance(pCreature->GetInstanceScript()), + isSacraficeTarget(false) { - npc_twilight_volunteerAI(Creature* pCreature) : ScriptedAI(pCreature), - pInstance(pCreature->GetInstanceScript()), - isSacraficeTarget(false) - { - } - - void DoAction(int32 action) override - { - if (action == ACTION_RITUAL_BEGIN) - { - isSacraficeTarget = true; - me->SetRegeneratingHealth(false); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - DoCastSelf(SPELL_ACTIVATE_INITIATE, true); - me->RemoveAurasDueToSpell(SPELL_WHITE_SPHERE); - me->SetControlled(false, UNIT_STATE_STUNNED); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_IMMUNE_TO_PC); - - Talk(SAY_CHOSEN); - me->SetStandState(UNIT_STAND_STATE_STAND); - - events.ScheduleEvent(EVENT_RITUAL_BEGIN_MOVE, 1500); - } - } - - void EnterEvadeMode() override - { - if (!isSacraficeTarget) - { - ScriptedAI::EnterEvadeMode(); - } - } - - void AttackStart(Unit* who) override - { - if (!isSacraficeTarget) - { - ScriptedAI::AttackStart(who); - } - } - - void MovementInform(uint32 type, uint32 id) override - { - if (type != POINT_MOTION_TYPE) - { - return; - } - - if (id == POINT_INITIAL) - { - me->SetFacingTo(me->GetAngle(&JedogaPosition[0])); - me->SendMovementFlagUpdate(); - DoCastSelf(SPELL_WHITE_SPHERE, false); - me->SetControlled(true, UNIT_STATE_STUNNED); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - } - else if (id == POINT_RITUAL) - { - if (Creature* jedoga = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(DATA_JEDOGA_SHADOWSEEKER))) - { - jedoga->AI()->Talk(SAY_SACRIFICE_2); - jedoga->CastSpell(nullptr, SPELL_SACRIFICE_BEAM); - - if (Creature* ritualTrigger = jedoga->SummonCreature(NPC_JEDOGA_CONTROLLER, JedogaPosition[2], TEMPSUMMON_TIMED_DESPAWN, 5000)) - { - ritualTrigger->CastSpell(ritualTrigger, SPELL_SACRIFICE_VISUAL); - } - } - - Talk(SAY_SACRIFICED); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - } - } - - void UpdateAI(uint32 diff) override - { - if (!events.Empty()) - { - events.Update(diff); - if (events.ExecuteEvent() == EVENT_RITUAL_BEGIN_MOVE) - { - me->GetMotionMaster()->Clear(); - me->SetHomePosition(JedogaPosition[2]); - me->SetWalk(true); - me->GetMotionMaster()->MovePoint(POINT_RITUAL, JedogaPosition[2], false); - } - } - - if (!isSacraficeTarget && UpdateVictim()) - { - DoMeleeAttackIfReady(); - } - } - - private: - InstanceScript* pInstance; - EventMap events; - bool isSacraficeTarget; - }; - - CreatureAI *GetAI(Creature *creature) const override - { - return GetAhnKahetAI(creature); } + + void DoAction(int32 action) override + { + if (action == ACTION_RITUAL_BEGIN) + { + isSacraficeTarget = true; + me->SetRegeneratingHealth(false); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + DoCastSelf(SPELL_ACTIVATE_INITIATE, true); + me->RemoveAurasDueToSpell(SPELL_WHITE_SPHERE); + me->SetControlled(false, UNIT_STATE_STUNNED); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_IMMUNE_TO_PC); + + Talk(SAY_CHOSEN); + me->SetStandState(UNIT_STAND_STATE_STAND); + + events.ScheduleEvent(EVENT_RITUAL_BEGIN_MOVE, 1500); + } + } + + void EnterEvadeMode() override + { + if (!isSacraficeTarget) + { + ScriptedAI::EnterEvadeMode(); + } + } + + void AttackStart(Unit* who) override + { + if (!isSacraficeTarget) + { + ScriptedAI::AttackStart(who); + } + } + + void MovementInform(uint32 type, uint32 id) override + { + if (type != POINT_MOTION_TYPE) + { + return; + } + + if (id == POINT_INITIAL) + { + me->SetFacingTo(me->GetAngle(&JedogaPosition[0])); + me->SendMovementFlagUpdate(); + DoCastSelf(SPELL_WHITE_SPHERE, false); + me->SetControlled(true, UNIT_STATE_STUNNED); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + } + else if (id == POINT_RITUAL) + { + if (Creature* jedoga = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(DATA_JEDOGA_SHADOWSEEKER))) + { + jedoga->AI()->Talk(SAY_SACRIFICE_2); + jedoga->CastSpell(nullptr, SPELL_SACRIFICE_BEAM); + + if (Creature* ritualTrigger = jedoga->SummonCreature(NPC_JEDOGA_CONTROLLER, JedogaPosition[2], TEMPSUMMON_TIMED_DESPAWN, 5000)) + { + ritualTrigger->CastSpell(ritualTrigger, SPELL_SACRIFICE_VISUAL); + } + } + + Talk(SAY_SACRIFICED); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + } + } + + void UpdateAI(uint32 diff) override + { + if (!events.Empty()) + { + events.Update(diff); + if (events.ExecuteEvent() == EVENT_RITUAL_BEGIN_MOVE) + { + me->GetMotionMaster()->Clear(); + me->SetHomePosition(JedogaPosition[2]); + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(POINT_RITUAL, JedogaPosition[2], false); + } + } + + if (!isSacraficeTarget && UpdateVictim()) + { + DoMeleeAttackIfReady(); + } + } + +private: + InstanceScript* pInstance; + EventMap events; + bool isSacraficeTarget; }; // 56328 - Random Lightning Visual Effect -class spell_random_lightning_visual_effect : public SpellScriptLoader +class spell_random_lightning_visual_effect : public SpellScript { - public: - spell_random_lightning_visual_effect() : SpellScriptLoader("spell_random_lightning_visual_effect") { } + PrepareSpellScript(spell_random_lightning_visual_effect); - class spell_random_lightning_visual_effect_SpellScript : public SpellScript + void ModDestHeight(SpellDestination& dest) { - PrepareSpellScript(spell_random_lightning_visual_effect_SpellScript); + Position const offset = { frand(-15.0f, 15.0f), frand(-15.0f, 15.0f), -19.0f, 0.0f }; + dest.RelocateOffset(offset); + } - void ModDestHeight(SpellDestination& dest) - { - Position const offset = { frand(-15.0f, 15.0f), frand(-15.0f, 15.0f), -19.0f, 0.0f }; - dest.RelocateOffset(offset); - } - - void Register() override - { - OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_random_lightning_visual_effect_SpellScript::ModDestHeight, EFFECT_0, TARGET_DEST_CASTER_RANDOM); - } - }; - - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_random_lightning_visual_effect_SpellScript(); + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_random_lightning_visual_effect::ModDestHeight, EFFECT_0, TARGET_DEST_CASTER_RANDOM); } }; // 56150 - Sacrifice Beam -class spell_jedoga_sacrafice_beam : public SpellScriptLoader +class spell_jedoga_sacrafice_beam : public AuraScript { - public: - spell_jedoga_sacrafice_beam() : SpellScriptLoader("spell_jedoga_sacrafice_beam") { } + PrepareAuraScript(spell_jedoga_sacrafice_beam); - class spell_jedoga_sacrafice_beam_AuraScript : public AuraScript + bool Load() override { - PrepareAuraScript(spell_jedoga_sacrafice_beam_AuraScript); + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } - bool Load() override - { - return GetCaster()->GetTypeId() == TYPEID_UNIT; - } - - void HandleRemoval(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - AuraRemoveMode const removeMode = GetTargetApplication()->GetRemoveMode(); - if (removeMode == AURA_REMOVE_BY_DEFAULT || removeMode == AURA_REMOVE_BY_EXPIRE) - { - GetCaster()->ToCreature()->AI()->DoAction(ACTION_SACRAFICE); - } - } - - void Register() override - { - AfterEffectRemove += AuraEffectRemoveFn(spell_jedoga_sacrafice_beam_AuraScript::HandleRemoval, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override + void HandleRemoval(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - return new spell_jedoga_sacrafice_beam_AuraScript(); + AuraRemoveMode const removeMode = GetTargetApplication()->GetRemoveMode(); + if (removeMode == AURA_REMOVE_BY_DEFAULT || removeMode == AURA_REMOVE_BY_EXPIRE) + { + GetCaster()->ToCreature()->AI()->DoAction(ACTION_SACRAFICE); + } + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_jedoga_sacrafice_beam::HandleRemoval, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); } }; @@ -776,12 +731,12 @@ class achievement_volunteer_work : public AchievementCriteriaScript void AddSC_boss_jedoga_shadowseeker() { // Creatures - new boss_jedoga_shadowseeker(); - new npc_twilight_volunteer(); + RegisterAhnKahetCreatureAI(boss_jedoga_shadowseeker); + RegisterAhnKahetCreatureAI(npc_twilight_volunteer); // Spells - new spell_random_lightning_visual_effect(); - new spell_jedoga_sacrafice_beam(); + RegisterSpellScript(spell_random_lightning_visual_effect); + RegisterSpellScript(spell_jedoga_sacrafice_beam); // Achievements new achievement_volunteer_work(); diff --git a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_prince_taldaram.cpp index 28058bcbe..7af166776 100644 --- a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_prince_taldaram.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_prince_taldaram.cpp @@ -93,438 +93,415 @@ constexpr float DATA_GROUND_POSITION_Z = 11.308135f; constexpr float DATA_SPHERE_DISTANCE = 25.0f; #define DATA_SPHERE_ANGLE_OFFSET float(M_PI) / 2.0f -class npc_taldaram_flamesphere : public CreatureScript +struct npc_taldaram_flamesphere : public NullCreatureAI { -public: - npc_taldaram_flamesphere() : CreatureScript("npc_taldaram_flamesphere") { } - - struct npc_taldaram_flamesphereAI : public NullCreatureAI + npc_taldaram_flamesphere(Creature *pCreature) : NullCreatureAI(pCreature), + instance(pCreature->GetInstanceScript()), + uiDespawnTimer(13000), + moveTimer(0) { - npc_taldaram_flamesphereAI(Creature *pCreature) : NullCreatureAI(pCreature), - instance(pCreature->GetInstanceScript()), - uiDespawnTimer(13000), - moveTimer(0) + pCreature->SetReactState(REACT_PASSIVE); + } + + void DoAction(int32 action) override + { + if (action == ACTION_SPHERE) { - pCreature->SetReactState(REACT_PASSIVE); + moveTimer = 3000; + } + } + + void MovementInform(uint32 type, uint32 id) override + { + if (type == POINT_MOTION_TYPE && id == POINT_ORB) + { + me->DisappearAndDie(); + } + } + + void IsSummonedBy(Unit* /*summoner*/) override + { + // Replace sphere instantly if sphere is summoned after prince death + if (instance->GetBossState(DATA_PRINCE_TALDARAM) != IN_PROGRESS) + { + me->DespawnOrUnsummon(); + return; } - void DoAction(int32 action) override + DoCastSelf(SPELL_FLAME_SPHERE_SPAWN_EFFECT); + DoCastSelf(SPELL_FLAME_SPHERE_VISUAL); + + // TODO: replace with DespawnOrUnsummon + uiDespawnTimer = 13000; + } + + void JustDied(Unit* /*who*/) override + { + DoCastSelf(SPELL_FLAME_SPHERE_DEATH_EFFECT); + } + + void UpdateAI(uint32 diff) override + { + if (moveTimer) { - if (action == ACTION_SPHERE) + if (moveTimer <= diff) { - moveTimer = 3000; + DoCastSelf(SPELL_FLAME_SPHERE_PERIODIC); + float angleOffset = 0.0f; + + switch (me->GetEntry()) + { + case NPC_FLAME_SPHERE_1: + break; + case NPC_FLAME_SPHERE_2: + angleOffset = DATA_SPHERE_ANGLE_OFFSET; + break; + case NPC_FLAME_SPHERE_3: + angleOffset = -DATA_SPHERE_ANGLE_OFFSET; + break; + default: + return; + } + + float angle = me->GetAngle(&victimPos) + angleOffset; + float x = me->GetPositionX() + DATA_SPHERE_DISTANCE * cos(angle); + float y = me->GetPositionY() + DATA_SPHERE_DISTANCE * sin(angle); + me->GetMotionMaster()->MovePoint(POINT_ORB, x, y, me->GetPositionZ()); + + moveTimer = 0; + } + else + { + moveTimer -= diff; } } - void MovementInform(uint32 type, uint32 id) override + if (uiDespawnTimer) { - if (type == POINT_MOTION_TYPE && id == POINT_ORB) + if (uiDespawnTimer <= diff) { me->DisappearAndDie(); + uiDespawnTimer = 0; } + else + uiDespawnTimer -= diff; } - - void IsSummonedBy(Unit* /*summoner*/) override - { - // Replace sphere instantly if sphere is summoned after prince death - if (instance->GetBossState(DATA_PRINCE_TALDARAM) != IN_PROGRESS) - { - me->DespawnOrUnsummon(); - return; - } - - DoCastSelf(SPELL_FLAME_SPHERE_SPAWN_EFFECT); - DoCastSelf(SPELL_FLAME_SPHERE_VISUAL); - - // TODO: replace with DespawnOrUnsummon - uiDespawnTimer = 13000; - } - - void JustDied(Unit* /*who*/) override - { - DoCastSelf(SPELL_FLAME_SPHERE_DEATH_EFFECT); - } - - void UpdateAI(uint32 diff) override - { - if (moveTimer) - { - if (moveTimer <= diff) - { - DoCastSelf(SPELL_FLAME_SPHERE_PERIODIC); - float angleOffset = 0.0f; - - switch (me->GetEntry()) - { - case NPC_FLAME_SPHERE_1: - break; - case NPC_FLAME_SPHERE_2: - angleOffset = DATA_SPHERE_ANGLE_OFFSET; - break; - case NPC_FLAME_SPHERE_3: - angleOffset = -DATA_SPHERE_ANGLE_OFFSET; - break; - default: - return; - } - - float angle = me->GetAngle(&victimPos) + angleOffset; - float x = me->GetPositionX() + DATA_SPHERE_DISTANCE * cos(angle); - float y = me->GetPositionY() + DATA_SPHERE_DISTANCE * sin(angle); - me->GetMotionMaster()->MovePoint(POINT_ORB, x, y, me->GetPositionZ()); - - moveTimer = 0; - } - else - { - moveTimer -= diff; - } - } - - if (uiDespawnTimer) - { - if (uiDespawnTimer <= diff) - { - me->DisappearAndDie(); - uiDespawnTimer = 0; - } - else - uiDespawnTimer -= diff; - } - } - - void SetVictimPos(Position const& pos) - { - victimPos.Relocate(pos); - } - - private: - Position victimPos; - InstanceScript* instance; - uint32 uiDespawnTimer; - uint32 moveTimer; - }; - - CreatureAI *GetAI(Creature *creature) const override - { - return GetAhnKahetAI(creature); } + + void SetVictimPos(Position const& pos) + { + victimPos.Relocate(pos); + } + +private: + Position victimPos; + InstanceScript* instance; + uint32 uiDespawnTimer; + uint32 moveTimer; }; -class boss_taldaram : public CreatureScript +struct boss_taldaram : public BossAI { -public: - boss_taldaram() : CreatureScript("boss_taldaram") + boss_taldaram(Creature* pCreature) : BossAI(pCreature, DATA_PRINCE_TALDARAM), + vanishDamage(0) { } - struct boss_taldaramAI : public BossAI + void InitializeAI() override { - boss_taldaramAI(Creature* pCreature) : BossAI(pCreature, DATA_PRINCE_TALDARAM), - vanishDamage(0) - { - } + BossAI::InitializeAI(); - void InitializeAI() override + // Event not started + if (instance->GetData(DATA_TELDRAM_SPHERE1) != DONE || instance->GetData(DATA_TELDRAM_SPHERE2) != DONE) { - BossAI::InitializeAI(); - - // Event not started - if (instance->GetData(DATA_TELDRAM_SPHERE1) != DONE || instance->GetData(DATA_TELDRAM_SPHERE2) != DONE) + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + me->SetDisableGravity(true); + me->SetHover(true); + if (!me->HasAura(SPELL_BEAM_VISUAL)) { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); - me->SetDisableGravity(true); - me->SetHover(true); - if (!me->HasAura(SPELL_BEAM_VISUAL)) - { - DoCastSelf(SPELL_BEAM_VISUAL, true); - } - - me->SummonCreatureGroup(SUMMON_GROUP_TRIGGERS); - return; + DoCastSelf(SPELL_BEAM_VISUAL, true); } - if (instance->GetData(DATA_TELDRAM_SPHERE1) == DONE && instance->GetData(DATA_TELDRAM_SPHERE2) == DONE) + me->SummonCreatureGroup(SUMMON_GROUP_TRIGGERS); + return; + } + + if (instance->GetData(DATA_TELDRAM_SPHERE1) == DONE && instance->GetData(DATA_TELDRAM_SPHERE2) == DONE) + { + DoAction(ACTION_REMOVE_PRISON_AT_RESET); + } + } + + void Reset() override + { + _Reset(); + + vanishDamage = 0; + vanishTarget_GUID.Clear(); + } + + void DoAction(int32 action) override + { + if (action == ACTION_REMOVE_PRISON || action == ACTION_REMOVE_PRISON_AT_RESET) + { + me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), DATA_GROUND_POSITION_Z, me->GetOrientation()); + instance->HandleGameObject(instance->GetGuidData(DATA_PRINCE_TALDARAM_PLATFORM), true); + + if (action == ACTION_REMOVE_PRISON) { - DoAction(ACTION_REMOVE_PRISON_AT_RESET); + DoCastSelf(SPELL_HOVER_FALL); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveLand(POINT_LAND, me->GetHomePosition(), 8.0f); + Talk(SAY_REMOVE_PRISON); } - } - - void Reset() override - { - _Reset(); - - vanishDamage = 0; - vanishTarget_GUID.Clear(); - } - - void DoAction(int32 action) override - { - if (action == ACTION_REMOVE_PRISON || action == ACTION_REMOVE_PRISON_AT_RESET) - { - me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), DATA_GROUND_POSITION_Z, me->GetOrientation()); - instance->HandleGameObject(instance->GetGuidData(DATA_PRINCE_TALDARAM_PLATFORM), true); - - if (action == ACTION_REMOVE_PRISON) - { - DoCastSelf(SPELL_HOVER_FALL); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveLand(POINT_LAND, me->GetHomePosition(), 8.0f); - Talk(SAY_REMOVE_PRISON); - } - // Teleport instantly - else - { - me->SetDisableGravity(false); - me->SetHover(false); - me->RemoveAllAuras(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NOT_SELECTABLE); - me->UpdatePosition(me->GetHomePosition(), true); - } - summons.DespawnEntry(NPC_JEDOGA_CONTROLLER); - } - } - - void MovementInform(uint32 type, uint32 id) override - { - if (type == EFFECT_MOTION_TYPE && id == POINT_LAND) + // Teleport instantly + else { me->SetDisableGravity(false); me->SetHover(false); me->RemoveAllAuras(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NOT_SELECTABLE); + me->UpdatePosition(me->GetHomePosition(), true); } + summons.DespawnEntry(NPC_JEDOGA_CONTROLLER); } + } - void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*school*/) override + void MovementInform(uint32 type, uint32 id) override + { + if (type == EFFECT_MOTION_TYPE && id == POINT_LAND) { - if (vanishTarget_GUID) - { - if (me->FindCurrentSpellBySpellId(SPELL_EMBRACE_OF_THE_VAMPYR)) - { - vanishDamage += damage; - if (vanishDamage >= DUNGEON_MODE(MAX_EMBRACE_DMG, MAX_EMBRACE_DMG_H)) - { - ScheduleCombatEvents(); - me->CastStop(); - vanishTarget_GUID.Clear(); - vanishDamage = 0; - } - } - } - } - - void JustDied(Unit* /*killer*/) override - { - _JustDied(); - Talk(SAY_DEATH); - } - - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() != TYPEID_PLAYER) - { - return; - } - - Talk(SAY_SLAY); - - if (vanishTarget_GUID && victim->GetGUID() == vanishTarget_GUID) - { - vanishTarget_GUID.Clear(); - vanishDamage = 0; - } - } - - void EnterCombat(Unit* /*who*/) override - { - _EnterCombat(); - Talk(SAY_AGGRO); - ScheduleCombatEvents(); - + me->SetDisableGravity(false); + me->SetHover(false); me->RemoveAllAuras(); - me->InterruptNonMeleeSpells(true); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NOT_SELECTABLE); } + } - void SpellHitTarget(Unit* /*target*/, const SpellInfo *spellInfo) override + void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*school*/) override + { + if (vanishTarget_GUID) { - if (spellInfo->Id == SPELL_CONJURE_FLAME_SPHERE) + if (me->FindCurrentSpellBySpellId(SPELL_EMBRACE_OF_THE_VAMPYR)) { - summons.DoAction(ACTION_SPHERE); + vanishDamage += damage; + if (vanishDamage >= DUNGEON_MODE(MAX_EMBRACE_DMG, MAX_EMBRACE_DMG_H)) + { + ScheduleCombatEvents(); + me->CastStop(); + vanishTarget_GUID.Clear(); + vanishDamage = 0; + } } } + } - void JustSummoned(Creature* summon) override + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + Talk(SAY_DEATH); + } + + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() != TYPEID_PLAYER) { - summons.Summon(summon); - switch (summon->GetEntry()) + return; + } + + Talk(SAY_SLAY); + + if (vanishTarget_GUID && victim->GetGUID() == vanishTarget_GUID) + { + vanishTarget_GUID.Clear(); + vanishDamage = 0; + } + } + + void EnterCombat(Unit* /*who*/) override + { + _EnterCombat(); + Talk(SAY_AGGRO); + ScheduleCombatEvents(); + + me->RemoveAllAuras(); + me->InterruptNonMeleeSpells(true); + } + + void SpellHitTarget(Unit* /*target*/, const SpellInfo *spellInfo) override + { + if (spellInfo->Id == SPELL_CONJURE_FLAME_SPHERE) + { + summons.DoAction(ACTION_SPHERE); + } + } + + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + switch (summon->GetEntry()) + { + case NPC_FLAME_SPHERE_1: + case NPC_FLAME_SPHERE_2: + case NPC_FLAME_SPHERE_3: { - case NPC_FLAME_SPHERE_1: - case NPC_FLAME_SPHERE_2: - case NPC_FLAME_SPHERE_3: + if (npc_taldaram_flamesphere* summonAI = dynamic_cast(summon->AI())) { - if (npc_taldaram_flamesphere::npc_taldaram_flamesphereAI* summonAI = dynamic_cast(summon->AI())) + summonAI->SetVictimPos(victimSperePos); + } + + break; + } + case NPC_JEDOGA_CONTROLLER: + { + summon->CastSpell(nullptr, SPELL_BEAM_VISUAL); + break; + } + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + { + return; + } + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + { + return; + } + + while (uint32 const eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_PRINCE_BLOODTHIRST: + { + DoCastSelf(SPELL_BLOODTHIRST); + events.RepeatEvent(10000); + break; + } + case EVENT_PRINCE_FLAME_SPHERES: + { + if (Unit* victim = me->GetVictim()) { - summonAI->SetVictimPos(victimSperePos); + DoCast(victim, SPELL_CONJURE_FLAME_SPHERE); + victimSperePos = *victim; } + if (!events.GetNextEventTime(EVENT_PRINCE_VANISH)) + { + events.RescheduleEvent(EVENT_PRINCE_VANISH, 14000); + } + else + { + // Make sure that Vanish won't get triggered at same time as sphere summon + events.DelayEvents(4000); + } + + events.RepeatEvent(15000); break; } - case NPC_JEDOGA_CONTROLLER: + case EVENT_PRINCE_VANISH: { - summon->CastSpell(nullptr, SPELL_BEAM_VISUAL); + //Count alive players + uint8 count = 0; + std::list const t_list = me->getThreatMgr().getThreatList(); + if (!t_list.empty()) + { + for (HostileReference const* reference : t_list) + { + if (reference) + { + Unit const* pTarget = ObjectAccessor::GetUnit(*me, reference->getUnitGuid()); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->IsAlive()) + { + ++count; + } + } + } + } + + // He only vanishes if there are 3 or more alive players + if (count > 2) + { + Talk(SAY_VANISH); + DoCastSelf(SPELL_VANISH, false); + if (Unit* pEmbraceTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + vanishTarget_GUID = pEmbraceTarget->GetGUID(); + } + + events.CancelEvent(EVENT_PRINCE_FLAME_SPHERES); + events.CancelEvent(EVENT_PRINCE_BLOODTHIRST); + events.ScheduleEvent(EVENT_PRINCE_VANISH_RUN, 2499); + } + break; + } + case EVENT_PRINCE_VANISH_RUN: + { + if (Unit* _vanishTarget = ObjectAccessor::GetUnit(*me, vanishTarget_GUID)) + { + vanishDamage = 0; + DoCast(_vanishTarget, SPELL_SHADOWSTEP); + me->CastSpell(_vanishTarget, SPELL_EMBRACE_OF_THE_VAMPYR, false); + me->RemoveAura(SPELL_VANISH); + } + + events.ScheduleEvent(EVENT_PRINCE_RESCHEDULE, 20000); + break; + } + case EVENT_PRINCE_RESCHEDULE: + { + ScheduleCombatEvents(); break; } } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - { - return; - } - - events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) { return; } - - while (uint32 const eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_PRINCE_BLOODTHIRST: - { - DoCastSelf(SPELL_BLOODTHIRST); - events.RepeatEvent(10000); - break; - } - case EVENT_PRINCE_FLAME_SPHERES: - { - if (Unit* victim = me->GetVictim()) - { - DoCast(victim, SPELL_CONJURE_FLAME_SPHERE); - victimSperePos = *victim; - } - - if (!events.GetNextEventTime(EVENT_PRINCE_VANISH)) - { - events.RescheduleEvent(EVENT_PRINCE_VANISH, 14000); - } - else - { - // Make sure that Vanish won't get triggered at same time as sphere summon - events.DelayEvents(4000); - } - - events.RepeatEvent(15000); - break; - } - case EVENT_PRINCE_VANISH: - { - //Count alive players - uint8 count = 0; - std::list const t_list = me->getThreatMgr().getThreatList(); - if (!t_list.empty()) - { - for (HostileReference const* reference : t_list) - { - if (reference) - { - Unit const* pTarget = ObjectAccessor::GetUnit(*me, reference->getUnitGuid()); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->IsAlive()) - { - ++count; - } - } - } - } - - // He only vanishes if there are 3 or more alive players - if (count > 2) - { - Talk(SAY_VANISH); - DoCastSelf(SPELL_VANISH, false); - if (Unit* pEmbraceTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - vanishTarget_GUID = pEmbraceTarget->GetGUID(); - } - - events.CancelEvent(EVENT_PRINCE_FLAME_SPHERES); - events.CancelEvent(EVENT_PRINCE_BLOODTHIRST); - events.ScheduleEvent(EVENT_PRINCE_VANISH_RUN, 2499); - } - break; - } - case EVENT_PRINCE_VANISH_RUN: - { - if (Unit* _vanishTarget = ObjectAccessor::GetUnit(*me, vanishTarget_GUID)) - { - vanishDamage = 0; - DoCast(_vanishTarget, SPELL_SHADOWSTEP); - me->CastSpell(_vanishTarget, SPELL_EMBRACE_OF_THE_VAMPYR, false); - me->RemoveAura(SPELL_VANISH); - } - - events.ScheduleEvent(EVENT_PRINCE_RESCHEDULE, 20000); - break; - } - case EVENT_PRINCE_RESCHEDULE: - { - ScheduleCombatEvents(); - break; - } - } - - if (me->HasUnitState(UNIT_STATE_CASTING)) - { - return; - } - } - - if (me->IsVisible()) - { - DoMeleeAttackIfReady(); - } } - private: - Position victimSperePos; - ObjectGuid vanishTarget_GUID; - uint32 vanishDamage; - - void ScheduleCombatEvents() + if (me->IsVisible()) { - events.Reset(); - events.RescheduleEvent(EVENT_PRINCE_FLAME_SPHERES, 10000); - events.RescheduleEvent(EVENT_PRINCE_BLOODTHIRST, 10000); - vanishTarget_GUID.Clear(); - vanishDamage = 0; + DoMeleeAttackIfReady(); } - }; + } - CreatureAI* GetAI(Creature* creature) const override +private: + Position victimSperePos; + ObjectGuid vanishTarget_GUID; + uint32 vanishDamage; + + void ScheduleCombatEvents() { - return GetAhnKahetAI(creature); + events.Reset(); + events.RescheduleEvent(EVENT_PRINCE_FLAME_SPHERES, 10000); + events.RescheduleEvent(EVENT_PRINCE_BLOODTHIRST, 10000); + vanishTarget_GUID.Clear(); + vanishDamage = 0; } }; +// TODO: Turn into new script type when Gossips have been updated class go_prince_taldaram_sphere : public GameObjectScript { public: - go_prince_taldaram_sphere() : GameObjectScript("go_prince_taldaram_sphere") { } + go_prince_taldaram_sphere() : GameObjectScript("go_prince_taldaram_sphere") {} - bool OnGossipHello(Player* pPlayer, GameObject *go) override + bool OnGossipHello(Player* pPlayer, GameObject* go) override { if (pPlayer && pPlayer->IsInCombat()) { return true; } - InstanceScript *pInstance = go->GetInstanceScript(); + InstanceScript* pInstance = go->GetInstanceScript(); if (!pInstance) { return true; @@ -550,83 +527,61 @@ public: }; // 55931 - Conjure Flame Sphere -class spell_prince_taldaram_conjure_flame_sphere : public SpellScriptLoader +class spell_prince_taldaram_conjure_flame_sphere : public SpellScript { -public: - spell_prince_taldaram_conjure_flame_sphere() : SpellScriptLoader("spell_prince_taldaram_conjure_flame_sphere") { } + PrepareSpellScript(spell_prince_taldaram_conjure_flame_sphere); - class spell_prince_taldaram_conjure_flame_sphere_SpellScript : public SpellScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareSpellScript(spell_prince_taldaram_conjure_flame_sphere_SpellScript); + return ValidateSpellInfo({SPELL_FLAME_SPHERE_SUMMON_1, SPELL_FLAME_SPHERE_SUMMON_2, SPELL_FLAME_SPHERE_SUMMON_3}); + } - bool Validate(SpellInfo const* /*spellInfo*/) override - { - return ValidateSpellInfo({SPELL_FLAME_SPHERE_SUMMON_1, SPELL_FLAME_SPHERE_SUMMON_2, SPELL_FLAME_SPHERE_SUMMON_3}); - } - - void HandleScript(SpellEffIndex /*effIndex*/) - { - Unit* caster = GetCaster(); - if (!caster || caster->isDead()) - { - return; - } - - caster->CastSpell(caster, SPELL_FLAME_SPHERE_SUMMON_1, false, nullptr, nullptr, caster->GetGUID()); - - if (caster->GetMap()->IsHeroic()) - { - caster->CastSpell(caster, SPELL_FLAME_SPHERE_SUMMON_2, false, nullptr, nullptr, caster->GetGUID()); - caster->CastSpell(caster, SPELL_FLAME_SPHERE_SUMMON_3, false, nullptr, nullptr, caster->GetGUID()); - } - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_prince_taldaram_conjure_flame_sphere_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override + void HandleScript(SpellEffIndex /*effIndex*/) { - return new spell_prince_taldaram_conjure_flame_sphere_SpellScript(); + Unit* caster = GetCaster(); + if (!caster || caster->isDead()) + { + return; + } + + caster->CastSpell(caster, SPELL_FLAME_SPHERE_SUMMON_1, false, nullptr, nullptr, caster->GetGUID()); + + if (caster->GetMap()->IsHeroic()) + { + caster->CastSpell(caster, SPELL_FLAME_SPHERE_SUMMON_2, false, nullptr, nullptr, caster->GetGUID()); + caster->CastSpell(caster, SPELL_FLAME_SPHERE_SUMMON_3, false, nullptr, nullptr, caster->GetGUID()); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_prince_taldaram_conjure_flame_sphere::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); } }; // 55895, 59511, 59512 - Flame Sphere Summon -class spell_prince_taldaram_flame_sphere_summon : public SpellScriptLoader +class spell_prince_taldaram_flame_sphere_summon : public SpellScript { - public: - spell_prince_taldaram_flame_sphere_summon() : SpellScriptLoader("spell_prince_taldaram_flame_sphere_summon") { } + PrepareSpellScript(spell_prince_taldaram_flame_sphere_summon); - class spell_prince_taldaram_flame_sphere_summon_SpellScript : public SpellScript - { - PrepareSpellScript(spell_prince_taldaram_flame_sphere_summon_SpellScript); + void SetDest(SpellDestination& dest) + { + dest._position.m_positionZ = DATA_GROUND_POSITION_Z + 5.5f; + } - void SetDest(SpellDestination& dest) - { - dest._position.m_positionZ = DATA_GROUND_POSITION_Z + 5.5f; - } - - void Register() override - { - OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_prince_taldaram_flame_sphere_summon_SpellScript::SetDest, EFFECT_0, TARGET_DEST_CASTER); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_prince_taldaram_flame_sphere_summon_SpellScript(); - } + void Register() override + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_prince_taldaram_flame_sphere_summon::SetDest, EFFECT_0, TARGET_DEST_CASTER); + } }; void AddSC_boss_taldaram() { - new npc_taldaram_flamesphere(); - new boss_taldaram(); + RegisterAhnKahetCreatureAI(npc_taldaram_flamesphere); + RegisterAhnKahetCreatureAI(boss_taldaram); new go_prince_taldaram_sphere(); // Spells - new spell_prince_taldaram_conjure_flame_sphere(); - new spell_prince_taldaram_flame_sphere_summon(); + RegisterSpellScript(spell_prince_taldaram_conjure_flame_sphere); + RegisterSpellScript(spell_prince_taldaram_flame_sphere_summon); } diff --git a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/instance_ahnkahet.cpp b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/instance_ahnkahet.cpp index bc2283d8f..4924c4c8b 100644 --- a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/instance_ahnkahet.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/instance_ahnkahet.cpp @@ -257,34 +257,23 @@ public: // 56702 Shadow Sickle // 59103 Shadow Sickle -class spell_shadow_sickle_periodic_damage : public SpellScriptLoader +class spell_shadow_sickle_periodic_damage : public AuraScript { -public: - spell_shadow_sickle_periodic_damage() : SpellScriptLoader("spell_shadow_sickle_periodic_damage") { } + PrepareAuraScript(spell_shadow_sickle_periodic_damage); - class spell_shadow_sickle_periodic_damage_AuraScript : public AuraScript + void HandlePeriodic(AuraEffect const* /*aurEff*/) { - PrepareAuraScript(spell_shadow_sickle_periodic_damage_AuraScript); + GetCaster()->CastSpell(nullptr, SPELL_SHADOW_SICKLE); + } - void HandlePeriodic(AuraEffect const* /*aurEff*/) - { - GetCaster()->CastSpell(nullptr, SPELL_SHADOW_SICKLE); - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_shadow_sickle_periodic_damage_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; - - AuraScript* GetAuraScript() const override + void Register() override { - return new spell_shadow_sickle_periodic_damage_AuraScript(); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_shadow_sickle_periodic_damage::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); } }; void AddSC_instance_ahnkahet() { new instance_ahnkahet; - new spell_shadow_sickle_periodic_damage(); + RegisterSpellScript(spell_shadow_sickle_periodic_damage); }