/*
* 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);
}