/*
* This file is part of the TrinityCore 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 "ScriptMgr.h"
#include "baradin_hold.h"
#include "Containers.h"
#include "InstanceScript.h"
#include "ObjectAccessor.h"
#include "ScriptedCreature.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "TemporarySummon.h"
#include "Vehicle.h"
enum Spells
{
SPELL_SEARING_SHADOWS = 96913,
SPELL_FOCUSED_FIRE_FIRST_DAMAGE = 97212,
SPELL_FOCUSED_FIRE_TRIGGER = 96872,
SPELL_FOCUSED_FIRE_VISUAL = 96886,
SPELL_FOCUSED_FIRE = 96884,
SPELL_EYES_OF_OCCUTHAR = 96920,
SPELL_GAZE_OF_OCCUTHAR = 96942,
SPELL_OCCUTHARS_DESTUCTION = 96968,
SPELL_BERSERK = 47008
};
enum Events
{
EVENT_SEARING_SHADOWS = 1,
EVENT_FOCUSED_FIRE = 2,
EVENT_EYES_OF_OCCUTHAR = 3,
EVENT_BERSERK = 4,
EVENT_FOCUSED_FIRE_FIRST_DAMAGE = 1
};
enum Misc
{
MAX_OCCUTHAR_VEHICLE_SEATS = 7
};
class boss_occuthar : public CreatureScript
{
public:
boss_occuthar() : CreatureScript("boss_occuthar") { }
struct boss_occutharAI : public BossAI
{
boss_occutharAI(Creature* creature) : BossAI(creature, BOSS_OCCUTHAR),
_vehicle(me->GetVehicleKit())
{
ASSERT(_vehicle);
}
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
events.ScheduleEvent(EVENT_SEARING_SHADOWS, 8s);
events.ScheduleEvent(EVENT_FOCUSED_FIRE, 15s);
events.ScheduleEvent(EVENT_EYES_OF_OCCUTHAR, 30s);
events.ScheduleEvent(EVENT_BERSERK, 5min);
}
void EnterEvadeMode(EvadeReason why) override
{
BossAI::EnterEvadeMode(why);
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_DespawnAtEvade();
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
if (summon->GetEntry() == NPC_FOCUS_FIRE_DUMMY)
{
DoCast(summon, SPELL_FOCUSED_FIRE);
for (uint8 i = 0; i < MAX_OCCUTHAR_VEHICLE_SEATS; ++i)
{
if (Unit* vehicle = _vehicle->GetPassenger(i))
vehicle->CastSpell(summon, SPELL_FOCUSED_FIRE_VISUAL);
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SEARING_SHADOWS:
DoCastAOE(SPELL_SEARING_SHADOWS);
events.ScheduleEvent(EVENT_SEARING_SHADOWS, 25s);
break;
case EVENT_FOCUSED_FIRE:
DoCastAOE(SPELL_FOCUSED_FIRE_TRIGGER, true);
events.ScheduleEvent(EVENT_FOCUSED_FIRE, 15s);
break;
case EVENT_EYES_OF_OCCUTHAR:
DoCastAOE(SPELL_EYES_OF_OCCUTHAR);
events.RescheduleEvent(EVENT_FOCUSED_FIRE, 15s);
events.ScheduleEvent(EVENT_EYES_OF_OCCUTHAR, 60s);
break;
case EVENT_BERSERK:
DoCast(me, SPELL_BERSERK, true);
break;
default:
break;
}
}
}
private:
Vehicle* _vehicle;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetBaradinHoldAI(creature);
}
};
class npc_eyestalk : public CreatureScript
{
public:
npc_eyestalk() : CreatureScript("npc_eyestalk") { }
struct npc_eyestalkAI : public ScriptedAI
{
npc_eyestalkAI(Creature* creature) : ScriptedAI(creature),
_instance(creature->GetInstanceScript())
{
_damageCount = 0;
}
void IsSummonedBy(WorldObject* /*summoner*/) override
{
// player is the spellcaster so register summon manually
if (Creature* occuthar = _instance->GetCreature(BOSS_OCCUTHAR))
occuthar->AI()->JustSummoned(me);
}
void Reset() override
{
_events.Reset();
_events.ScheduleEvent(EVENT_FOCUSED_FIRE_FIRST_DAMAGE, 0s);
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
if (_events.ExecuteEvent() == EVENT_FOCUSED_FIRE_FIRST_DAMAGE)
{
DoCastAOE(SPELL_FOCUSED_FIRE_FIRST_DAMAGE);
if (++_damageCount < 2)
_events.ScheduleEvent(EVENT_FOCUSED_FIRE_FIRST_DAMAGE, 1s);
}
}
void EnterEvadeMode(EvadeReason /*why*/) override { } // Never evade
private:
InstanceScript* _instance;
EventMap _events;
uint8 _damageCount;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetBaradinHoldAI(creature);
}
};
// 96872 - Focused Fire
class spell_occuthar_focused_fire : public SpellScriptLoader
{
public:
spell_occuthar_focused_fire() : SpellScriptLoader("spell_occuthar_focused_fire") { }
class spell_occuthar_focused_fire_SpellScript : public SpellScript
{
void FilterTargets(std::list& targets)
{
if (targets.size() < 2)
return;
targets.remove_if([&](WorldObject const* target)
{
return GetCaster()->GetVictim() == target;
});
if (targets.size() >= 2)
Trinity::Containers::RandomResize(targets, 1);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_occuthar_focused_fire_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_occuthar_focused_fire_SpellScript();
}
};
// ID - 96931 Eyes of Occu'thar
class spell_occuthar_eyes_of_occuthar : public SpellScriptLoader
{
public:
spell_occuthar_eyes_of_occuthar() : SpellScriptLoader("spell_occuthar_eyes_of_occuthar") { }
class spell_occuthar_eyes_of_occuthar_SpellScript : public SpellScript
{
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellEffect({ { spellInfo->Id, EFFECT_0 } }) && ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) });
}
bool Load() override
{
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
void FilterTargets(std::list& targets)
{
if (targets.empty())
return;
Trinity::Containers::RandomResize(targets, 1);
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
GetHitUnit()->CastSpell(GetCaster(), GetEffectValue(), true);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_occuthar_eyes_of_occuthar_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
OnEffectHitTarget += SpellEffectFn(spell_occuthar_eyes_of_occuthar_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_occuthar_eyes_of_occuthar_SpellScript();
}
};
// ID - 96932 Eyes of Occu'thar
class spell_occuthar_eyes_of_occuthar_vehicle : public SpellScriptLoader
{
public:
spell_occuthar_eyes_of_occuthar_vehicle() : SpellScriptLoader("spell_occuthar_eyes_of_occuthar_vehicle") { }
class spell_occuthar_eyes_of_occuthar_vehicle_SpellScript : public SpellScript
{
bool Load() override
{
return InstanceHasScript(GetCaster(), BHScriptName);
}
void HandleScript()
{
Position pos = GetHitUnit()->GetPosition();
if (Creature* occuthar = GetCaster()->GetInstanceScript()->GetCreature(BOSS_OCCUTHAR))
{
if (Creature* creature = occuthar->SummonCreature(NPC_EYE_OF_OCCUTHAR, pos))
creature->CastSpell(GetHitUnit(), SPELL_GAZE_OF_OCCUTHAR, false);
}
}
void Register() override
{
AfterHit += SpellHitFn(spell_occuthar_eyes_of_occuthar_vehicle_SpellScript::HandleScript);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_occuthar_eyes_of_occuthar_vehicle_SpellScript();
}
};
// 96942 / 101009 - Gaze of Occu'thar
class spell_occuthar_occuthars_destruction : public SpellScriptLoader
{
public:
spell_occuthar_occuthars_destruction() : SpellScriptLoader("spell_occuthar_occuthars_destruction") { }
class spell_occuthar_occuthars_destruction_AuraScript : public AuraScript
{
bool Load() override
{
return GetCaster() && GetCaster()->GetTypeId() == TYPEID_UNIT;
}
void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
if (Unit* caster = GetCaster())
{
if (IsExpired())
caster->CastSpell(nullptr, SPELL_OCCUTHARS_DESTUCTION, aurEff);
caster->ToCreature()->DespawnOrUnsummon(500ms);
}
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_occuthar_occuthars_destruction_AuraScript::OnRemove, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_occuthar_occuthars_destruction_AuraScript();
}
};
void AddSC_boss_occuthar()
{
new boss_occuthar();
new npc_eyestalk();
new spell_occuthar_focused_fire();
new spell_occuthar_eyes_of_occuthar();
new spell_occuthar_eyes_of_occuthar_vehicle();
new spell_occuthar_occuthars_destruction();
}