/* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "AreaTriggerScript.h" #include "CreatureScript.h" #include "Player.h" #include "ScriptedCreature.h" #include "SpellScript.h" #include "SpellScriptLoader.h" #include "zulgurub.h" /* Name: Boss_Hakkar %Complete: 95 Comment: Blood siphon spell buggy cause of Core Issue. Category: Zul'Gurub */ enum Says { SAY_AGGRO = 0, SAY_FLEEING = 1, SAY_MINION_DESTROY = 2, SAY_PROTECT_ALTAR = 3, SAY_PROTECT_GURUBASHI_EMPIRE = 4, SAY_PLEDGE_ALLEGIANCE = 5, SAY_WORLD_WILL_SUFFER = 6, SAY_EVADE = 7 }; enum Spells { SPELL_BLOOD_SIPHON = 24324, SPELL_BLOOD_SIPHON_HEAL = 24322, SPELL_BLOOD_SIPHON_DAMAGE = 24323, SPELL_CORRUPTED_BLOOD = 24328, SPELL_CAUSE_INSANITY = 24327, SPELL_ENRAGE = 24318, // The Aspects of all High Priests spells SPELL_ASPECT_OF_JEKLIK = 24687, SPELL_ASPECT_OF_VENOXIS = 24688, SPELL_ASPECT_OF_MARLI = 24686, SPELL_ASPECT_OF_THEKAL = 24689, SPELL_ASPECT_OF_ARLOKK = 24690, SPELL_POISONOUS_BLOOD = 24321 }; enum Events { EVENT_BLOOD_SIPHON = 1, EVENT_CORRUPTED_BLOOD = 2, EVENT_CAUSE_INSANITY = 3, EVENT_ENRAGE = 4, // The Aspects of all High Priests events EVENT_ASPECT_OF_JEKLIK = 5, EVENT_ASPECT_OF_VENOXIS = 6, EVENT_ASPECT_OF_MARLI = 7, EVENT_ASPECT_OF_THEKAL = 8, EVENT_ASPECT_OF_ARLOKK = 9 }; class boss_hakkar : public CreatureScript { public: boss_hakkar() : CreatureScript("boss_hakkar") { } struct boss_hakkarAI : public BossAI { boss_hakkarAI(Creature* creature) : BossAI(creature, DATA_HAKKAR) { } bool CheckInRoom() override { if (me->GetPositionZ() < 52.f || me->GetPositionZ() > 57.28f) { BossAI::EnterEvadeMode(EVADE_REASON_BOUNDARY); return false; } return true; } void ApplyHakkarPowerStacks() { me->RemoveAurasDueToSpell(SPELL_HAKKAR_POWER); for (int i = DATA_JEKLIK; i < DATA_HAKKAR; i++) if (instance->GetBossState(i) != DONE) DoCastSelf(SPELL_HAKKAR_POWER, true); } void Reset() override { _Reset(); ApplyHakkarPowerStacks(); } void JustDied(Unit* /*killer*/) override { _JustDied(); } void JustEngagedWith(Unit* /*who*/) override { _JustEngagedWith(); events.ScheduleEvent(EVENT_BLOOD_SIPHON, 90s); events.ScheduleEvent(EVENT_CORRUPTED_BLOOD, 25s); events.ScheduleEvent(EVENT_CAUSE_INSANITY, 17s); events.ScheduleEvent(EVENT_ENRAGE, 1min); if (instance->GetBossState(DATA_JEKLIK) != DONE) events.ScheduleEvent(EVENT_ASPECT_OF_JEKLIK, 21s); if (instance->GetBossState(DATA_VENOXIS) != DONE) events.ScheduleEvent(EVENT_ASPECT_OF_VENOXIS, 14s); if (instance->GetBossState(DATA_MARLI) != DONE) events.ScheduleEvent(EVENT_ASPECT_OF_MARLI, 15s); if (instance->GetBossState(DATA_THEKAL) != DONE) events.ScheduleEvent(EVENT_ASPECT_OF_THEKAL, 10s); if (instance->GetBossState(DATA_ARLOKK) != DONE) events.ScheduleEvent(EVENT_ASPECT_OF_ARLOKK, 18s); Talk(SAY_AGGRO); } void EnterEvadeMode(EvadeReason evadeReason) override { BossAI::EnterEvadeMode(evadeReason); Talk(SAY_EVADE); } void UpdateAI(uint32 diff) override { if (!UpdateVictim() || !CheckInRoom()) return; events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) return; while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { case EVENT_BLOOD_SIPHON: DoCastAOE(SPELL_BLOOD_SIPHON, true); events.ScheduleEvent(EVENT_BLOOD_SIPHON, 90s); break; case EVENT_CORRUPTED_BLOOD: DoCastVictim(SPELL_CORRUPTED_BLOOD, true); events.ScheduleEvent(EVENT_CORRUPTED_BLOOD, 30s, 40s); break; case EVENT_CAUSE_INSANITY: if (me->GetThreatMgr().GetThreatListSize() > 1) { if (Unit* victim = SelectTarget(SelectTargetMethod::MaxThreat, 0, 30.f, true)) { DoCast(victim, SPELL_CAUSE_INSANITY); } } events.ScheduleEvent(EVENT_CAUSE_INSANITY, 35s, 40s); break; case EVENT_ENRAGE: if (!me->HasAura(SPELL_ENRAGE)) DoCastSelf(SPELL_ENRAGE); events.ScheduleEvent(EVENT_ENRAGE, 90s); break; case EVENT_ASPECT_OF_JEKLIK: DoCastVictim(SPELL_ASPECT_OF_JEKLIK, true); events.ScheduleEvent(EVENT_ASPECT_OF_JEKLIK, 24s); break; case EVENT_ASPECT_OF_VENOXIS: DoCastVictim(SPELL_ASPECT_OF_VENOXIS, true); events.ScheduleEvent(EVENT_ASPECT_OF_VENOXIS, 16s, 18s); break; case EVENT_ASPECT_OF_MARLI: if (Unit* victim = SelectTarget(SelectTargetMethod::MaxThreat, 0, 5.f, true)) { DoCast(victim, SPELL_ASPECT_OF_MARLI, true); me->GetThreatMgr().ModifyThreatByPercent(victim, -100.f); } events.ScheduleEvent(EVENT_ASPECT_OF_MARLI, 45s); break; case EVENT_ASPECT_OF_THEKAL: DoCastVictim(SPELL_ASPECT_OF_THEKAL, true); events.ScheduleEvent(EVENT_ASPECT_OF_THEKAL, 15s); break; case EVENT_ASPECT_OF_ARLOKK: if (Unit* victim = SelectTarget(SelectTargetMethod::MaxThreat, 0, 5.f, true)) { DoCast(victim, SPELL_ASPECT_OF_ARLOKK, true); me->GetThreatMgr().ModifyThreatByPercent(victim, -100.f); } events.ScheduleEvent(EVENT_ASPECT_OF_ARLOKK, 10s, 15s); break; default: break; } } DoMeleeAttackIfReady(); } }; CreatureAI* GetAI(Creature* creature) const override { return GetZulGurubAI(creature); } }; class at_zulgurub_entrance_speech : public OnlyOnceAreaTriggerScript { public: at_zulgurub_entrance_speech() : OnlyOnceAreaTriggerScript("at_zulgurub_entrance_speech") {} bool _OnTrigger(Player* player, const AreaTrigger* /*at*/) override { if (InstanceScript* instance = player->GetInstanceScript()) { if (Creature* hakkar = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_HAKKAR))) { hakkar->setActive(true); if (hakkar->GetAI()) { hakkar->AI()->Talk(SAY_PROTECT_GURUBASHI_EMPIRE); } } } return false; } }; class at_zulgurub_bridge_speech : public OnlyOnceAreaTriggerScript { public: at_zulgurub_bridge_speech() : OnlyOnceAreaTriggerScript("at_zulgurub_bridge_speech") {} bool _OnTrigger(Player* player, const AreaTrigger* /*at*/) override { if (InstanceScript* instance = player->GetInstanceScript()) { if (Creature* hakkar = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_HAKKAR))) { if (hakkar->GetAI()) { hakkar->AI()->Talk(SAY_PROTECT_ALTAR); } } } return false; } }; class at_zulgurub_temple_speech : public OnlyOnceAreaTriggerScript { public: at_zulgurub_temple_speech() : OnlyOnceAreaTriggerScript("at_zulgurub_temple_speech") {} bool _OnTrigger(Player* player, const AreaTrigger* /*at*/) override { if (InstanceScript* instance = player->GetInstanceScript()) { if (Creature* hakkar = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_HAKKAR))) { if (hakkar->GetAI()) { hakkar->AI()->Talk(SAY_MINION_DESTROY); } } } return false; } }; class at_zulgurub_bloodfire_pit_speech : public OnlyOnceAreaTriggerScript { public: at_zulgurub_bloodfire_pit_speech() : OnlyOnceAreaTriggerScript("at_zulgurub_bloodfire_pit_speech") {} bool _OnTrigger(Player* player, const AreaTrigger* /*at*/) override { if (InstanceScript* instance = player->GetInstanceScript()) { if (Creature* hakkar = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_HAKKAR))) { if (hakkar->GetAI()) { hakkar->AI()->Talk(SAY_PLEDGE_ALLEGIANCE, player); } } } return false; } }; class at_zulgurub_edge_of_madness_speech : public OnlyOnceAreaTriggerScript { public: at_zulgurub_edge_of_madness_speech() : OnlyOnceAreaTriggerScript("at_zulgurub_edge_of_madness_speech") {} bool _OnTrigger(Player* player, const AreaTrigger* /*at*/) override { if (InstanceScript* instance = player->GetInstanceScript()) { if (Creature* hakkar = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_HAKKAR))) { if (hakkar->GetAI()) { hakkar->AI()->Talk(SAY_WORLD_WILL_SUFFER, player); } } } return false; } }; // 24324 - Blood Siphon (channel) class spell_blood_siphon : public SpellScript { PrepareSpellScript(spell_blood_siphon); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_BLOOD_SIPHON_DAMAGE, SPELL_BLOOD_SIPHON_HEAL }); } void FilterTargets(std::list& targets) { // Max. 20 targets if (!targets.empty()) { Acore::Containers::RandomResize(targets, 20); } } void HandleScriptEffect(SpellEffIndex /*effIndex*/) { if (Unit* caster = GetCaster()) { if (Player* player = GetHitPlayer()) { player->CastSpell(caster, player->HasAura(SPELL_POISONOUS_BLOOD) ? SPELL_BLOOD_SIPHON_DAMAGE : SPELL_BLOOD_SIPHON_HEAL, true); } } } void Register() override { OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_blood_siphon::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_blood_siphon::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; // 24323 - Blood Siphon (aura) | Effects changed in SpellInfoCorrections class spell_blood_siphon_aura : public AuraScript { PrepareAuraScript(spell_blood_siphon_aura); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_POISONOUS_BLOOD }); } void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { if (Unit* target = GetTarget()) { if (target->HasAura(SPELL_POISONOUS_BLOOD)) target->RemoveAurasDueToSpell(SPELL_POISONOUS_BLOOD); } } void Register() override { AfterEffectRemove += AuraEffectRemoveFn(spell_blood_siphon_aura::OnRemove, EFFECT_1, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); } }; // 24693 - Serverside - Hakkar Power Down class spell_hakkar_power_down : public SpellScript { PrepareSpellScript(spell_hakkar_power_down); void HandleOnHit() { if (Unit* caster = GetCaster()) if (caster->HasAura(SPELL_HAKKAR_POWER)) caster->RemoveAuraFromStack(SPELL_HAKKAR_POWER); } void Register() override { OnHit += SpellHitFn(spell_hakkar_power_down::HandleOnHit); } }; void AddSC_boss_hakkar() { new boss_hakkar(); new at_zulgurub_entrance_speech(); new at_zulgurub_bridge_speech(); new at_zulgurub_temple_speech(); new at_zulgurub_bloodfire_pit_speech(); new at_zulgurub_edge_of_madness_speech(); RegisterSpellScript(spell_blood_siphon); RegisterSpellScript(spell_blood_siphon_aura); RegisterSpellScript(spell_hakkar_power_down); }