forked from mirror/azerothcore-wotlk
431 lines
16 KiB
C++
431 lines
16 KiB
C++
/*
|
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license: http://github.com/azerothcore/azerothcore-wotlk/LICENSE-GPL2
|
|
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
|
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
|
*/
|
|
|
|
/* ScriptData
|
|
TCName: Boss_Arlokk
|
|
TC%Complete: 95
|
|
TCComment: Wrong cleave and red aura is missing not yet added.
|
|
TCComment: Prowlers moving through wall hopefully mmaps will fix.
|
|
TCComment: Can't test LOS until mmaps.
|
|
TCCategory: Zul'Gurub
|
|
EndScriptData */
|
|
|
|
#include "ScriptMgr.h"
|
|
#include "ScriptedCreature.h"
|
|
#include "SpellInfo.h"
|
|
#include "zulgurub.h"
|
|
|
|
enum Says
|
|
{
|
|
SAY_AGGRO = 0,
|
|
SAY_FEAST_PROWLER = 1,
|
|
SAY_DEATH = 2
|
|
};
|
|
|
|
enum Spells
|
|
{
|
|
SPELL_SHADOW_WORD_PAIN = 24212, // Corrected
|
|
SPELL_GOUGE = 12540, // Corrected
|
|
SPELL_MARK_OF_ARLOKK = 24210, // triggered spell 24211 Added to spell_dbc
|
|
SPELL_RAVAGE = 24213, // Corrected
|
|
SPELL_CLEAVE = 25174, // Searching for right spell
|
|
SPELL_PANTHER_TRANSFORM = 24190, // Transform to panther now used
|
|
SPELL_SUMMON_PROWLER = 24246, // Added to Spell_dbc
|
|
SPELL_VANISH_VISUAL = 24222, // Added
|
|
SPELL_VANISH = 24223, // Added
|
|
SPELL_SUPER_INVIS = 24235 // Added to Spell_dbc
|
|
};
|
|
|
|
enum Events
|
|
{
|
|
EVENT_SHADOW_WORD_PAIN = 1,
|
|
EVENT_GOUGE = 2,
|
|
EVENT_MARK_OF_ARLOKK = 3,
|
|
EVENT_RAVAGE = 4,
|
|
EVENT_TRANSFORM = 5,
|
|
EVENT_VANISH = 6,
|
|
EVENT_VANISH_2 = 7,
|
|
EVENT_TRANSFORM_BACK = 8,
|
|
EVENT_VISIBLE = 9,
|
|
EVENT_SUMMON_PROWLERS = 10
|
|
};
|
|
|
|
enum Phases
|
|
{
|
|
PHASE_ALL = 0,
|
|
PHASE_ONE = 1,
|
|
PHASE_TWO = 2
|
|
};
|
|
|
|
enum Weapon
|
|
{
|
|
WEAPON_DAGGER = 10616
|
|
};
|
|
|
|
enum Misc
|
|
{
|
|
MAX_PROWLERS_PER_SIDE = 15
|
|
};
|
|
|
|
Position const PosMoveOnSpawn[1] =
|
|
{
|
|
{ -11561.9f, -1627.868f, 41.29941f, 0.0f }
|
|
};
|
|
|
|
class boss_arlokk : public CreatureScript
|
|
{
|
|
public: boss_arlokk() : CreatureScript("boss_arlokk") { }
|
|
|
|
struct boss_arlokkAI : public BossAI
|
|
{
|
|
boss_arlokkAI(Creature* creature) : BossAI(creature, DATA_ARLOKK) { }
|
|
|
|
void Reset()
|
|
{
|
|
if (events.IsInPhase(PHASE_TWO))
|
|
me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack
|
|
_Reset();
|
|
_summonCountA = 0;
|
|
_summonCountB = 0;
|
|
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER));
|
|
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER));
|
|
me->SetWalk(false);
|
|
me->GetMotionMaster()->MovePoint(0, PosMoveOnSpawn[0]);
|
|
}
|
|
|
|
void JustDied(Unit* /*killer*/)
|
|
{
|
|
_JustDied();
|
|
Talk(SAY_DEATH);
|
|
}
|
|
|
|
void EnterCombat(Unit* /*who*/)
|
|
{
|
|
_EnterCombat();
|
|
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(7000, 9000), 0, PHASE_ONE);
|
|
events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE);
|
|
events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL);
|
|
events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(9000, 11000), 0, PHASE_ALL);
|
|
events.ScheduleEvent(EVENT_TRANSFORM, urand(15000, 20000), 0, PHASE_ONE);
|
|
Talk(SAY_AGGRO);
|
|
|
|
// Sets up list of Panther spawners to cast on
|
|
std::list<Creature*> triggerList;
|
|
GetCreatureListWithEntryInGrid(triggerList, me, NPC_PANTHER_TRIGGER, 100.0f);
|
|
if (!triggerList.empty())
|
|
{
|
|
uint8 sideA = 0;
|
|
uint8 sideB = 0;
|
|
for (std::list<Creature*>::const_iterator itr = triggerList.begin(); itr != triggerList.end(); ++itr)
|
|
{
|
|
if (Creature* trigger = *itr)
|
|
{
|
|
if (trigger->GetPositionY() < -1625.0f)
|
|
{
|
|
_triggersSideAGUID[sideA] = trigger->GetGUID();
|
|
++sideA;
|
|
}
|
|
else
|
|
{
|
|
_triggersSideBGUID[sideB] = trigger->GetGUID();
|
|
++sideB;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void EnterEvadeMode()
|
|
{
|
|
BossAI::EnterEvadeMode();
|
|
if (GameObject* object = ObjectAccessor::GetGameObject(*me, instance->GetData64(GO_GONG_OF_BETHEKK)))
|
|
object->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
|
me->DespawnOrUnsummon(4000);
|
|
}
|
|
|
|
void SetData(uint32 id, uint32 /*value*/)
|
|
{
|
|
if (id == 1)
|
|
--_summonCountA;
|
|
else if (id == 2)
|
|
--_summonCountB;
|
|
}
|
|
|
|
void UpdateAI(uint32 diff)
|
|
{
|
|
if (!UpdateVictim())
|
|
return;
|
|
|
|
events.Update(diff);
|
|
|
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
return;
|
|
|
|
while (uint32 eventId = events.ExecuteEvent())
|
|
{
|
|
switch (eventId)
|
|
{
|
|
case EVENT_SHADOW_WORD_PAIN:
|
|
DoCastVictim(SPELL_SHADOW_WORD_PAIN, true);
|
|
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(5000, 7000), 0, PHASE_ONE);
|
|
break;
|
|
case EVENT_GOUGE:
|
|
DoCastVictim(SPELL_GOUGE, true);
|
|
break;
|
|
case EVENT_SUMMON_PROWLERS:
|
|
if (_summonCountA < MAX_PROWLERS_PER_SIDE)
|
|
{
|
|
if (Unit* trigger = ObjectAccessor::GetUnit(*me, _triggersSideAGUID[urand(0, 4)]))
|
|
{
|
|
trigger->CastSpell(trigger, SPELL_SUMMON_PROWLER);
|
|
++_summonCountA;
|
|
}
|
|
}
|
|
if (_summonCountB < MAX_PROWLERS_PER_SIDE)
|
|
{
|
|
if (Unit* trigger = ObjectAccessor::GetUnit(*me, _triggersSideBGUID[urand(0, 4)]))
|
|
{
|
|
trigger->CastSpell(trigger, SPELL_SUMMON_PROWLER);
|
|
++_summonCountB;
|
|
}
|
|
}
|
|
events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL);
|
|
break;
|
|
case EVENT_MARK_OF_ARLOKK:
|
|
{
|
|
Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, urand(1, 3), 0.0f, false, -SPELL_MARK_OF_ARLOKK);
|
|
if (!target)
|
|
target = me->GetVictim();
|
|
if (target)
|
|
{
|
|
DoCast(target, SPELL_MARK_OF_ARLOKK, true);
|
|
Talk(SAY_FEAST_PROWLER, target);
|
|
}
|
|
events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(120000, 130000));
|
|
break;
|
|
}
|
|
case EVENT_TRANSFORM:
|
|
{
|
|
DoCast(me, SPELL_PANTHER_TRANSFORM); // SPELL_AURA_TRANSFORM
|
|
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP));
|
|
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(EQUIP_UNEQUIP));
|
|
/*
|
|
const CreatureTemplate* cinfo = me->GetCreatureTemplate();
|
|
me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35)));
|
|
me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35)));
|
|
me->UpdateDamagePhysical(BASE_ATTACK);
|
|
*/
|
|
me->AttackStop();
|
|
DoResetThreat();
|
|
me->SetReactState(REACT_PASSIVE);
|
|
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
|
|
DoCast(me, SPELL_VANISH_VISUAL);
|
|
DoCast(me, SPELL_VANISH);
|
|
events.ScheduleEvent(EVENT_VANISH, 1000, 0, PHASE_ONE);
|
|
break;
|
|
}
|
|
case EVENT_VANISH:
|
|
DoCast(me, SPELL_SUPER_INVIS);
|
|
me->SetWalk(false);
|
|
me->GetMotionMaster()->MovePoint(0, frand(-11551.0f, -11508.0f), frand(-1638.0f, -1617.0f), me->GetPositionZ());
|
|
events.ScheduleEvent(EVENT_VANISH_2, 9000, 0, PHASE_ONE);
|
|
break;
|
|
case EVENT_VANISH_2:
|
|
DoCast(me, SPELL_VANISH);
|
|
DoCast(me, SPELL_SUPER_INVIS);
|
|
events.ScheduleEvent(EVENT_VISIBLE, urand(7000, 10000), 0, PHASE_ONE);
|
|
break;
|
|
case EVENT_VISIBLE:
|
|
me->SetReactState(REACT_AGGRESSIVE);
|
|
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
|
|
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
|
AttackStart(target);
|
|
me->RemoveAura(SPELL_SUPER_INVIS);
|
|
me->RemoveAura(SPELL_VANISH);
|
|
events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO);
|
|
events.ScheduleEvent(EVENT_TRANSFORM_BACK, urand(15000, 18000), 0, PHASE_TWO);
|
|
events.SetPhase(PHASE_TWO);
|
|
me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, true); // hack
|
|
break;
|
|
case EVENT_RAVAGE:
|
|
DoCastVictim(SPELL_RAVAGE, true);
|
|
events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO);
|
|
break;
|
|
case EVENT_TRANSFORM_BACK:
|
|
{
|
|
me->RemoveAura(SPELL_PANTHER_TRANSFORM); // SPELL_AURA_TRANSFORM
|
|
DoCast(me, SPELL_VANISH_VISUAL);
|
|
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER));
|
|
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER));
|
|
/*
|
|
const CreatureTemplate* cinfo = me->GetCreatureTemplate();
|
|
me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg));
|
|
me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg));
|
|
me->UpdateDamagePhysical(BASE_ATTACK);
|
|
*/
|
|
me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack
|
|
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(4000, 7000), 0, PHASE_ONE);
|
|
events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE);
|
|
events.ScheduleEvent(EVENT_TRANSFORM, urand(16000, 20000), 0, PHASE_ONE);
|
|
events.SetPhase(PHASE_ONE);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
DoMeleeAttackIfReady();
|
|
}
|
|
|
|
private:
|
|
uint8 _summonCountA;
|
|
uint8 _summonCountB;
|
|
uint64 _triggersSideAGUID[5];
|
|
uint64 _triggersSideBGUID[5];
|
|
};
|
|
|
|
CreatureAI* GetAI(Creature* creature) const
|
|
{
|
|
return GetZulGurubAI<boss_arlokkAI>(creature);
|
|
}
|
|
};
|
|
|
|
/*######
|
|
## npc_zulian_prowler
|
|
######*/
|
|
|
|
enum ZulianProwlerSpells
|
|
{
|
|
SPELL_SNEAK_RANK_1_1 = 22766,
|
|
SPELL_SNEAK_RANK_1_2 = 7939, // Added to Spell_dbc
|
|
SPELL_MARK_OF_ARLOKK_TRIGGER = 24211 // Added to Spell_dbc
|
|
};
|
|
|
|
enum ZulianProwlerEvents
|
|
{
|
|
EVENT_ATTACK = 1
|
|
};
|
|
|
|
/*Position const PosProwlerCenter[1] =
|
|
{
|
|
{ -11556.7f, -1631.344f, 41.2994f, 0.0f }
|
|
};*/
|
|
|
|
class npc_zulian_prowler : public CreatureScript
|
|
{
|
|
public: npc_zulian_prowler() : CreatureScript("npc_zulian_prowler") { }
|
|
|
|
struct npc_zulian_prowlerAI : public ScriptedAI
|
|
{
|
|
npc_zulian_prowlerAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
|
|
|
|
void Reset()
|
|
{
|
|
if (me->GetPositionY() < -1625.0f)
|
|
_sideData = 1;
|
|
else
|
|
_sideData = 2;
|
|
|
|
DoCast(me, SPELL_SNEAK_RANK_1_1);
|
|
DoCast(me, SPELL_SNEAK_RANK_1_2);
|
|
|
|
if (Unit* arlokk = ObjectAccessor::GetUnit(*me, _instance->GetData64(NPC_ARLOKK)))
|
|
me->GetMotionMaster()->MovePoint(0, arlokk->GetPositionX(), arlokk->GetPositionY(), arlokk->GetPositionZ());
|
|
_events.ScheduleEvent(EVENT_ATTACK, 6000);
|
|
}
|
|
|
|
void EnterCombat(Unit* /*who*/)
|
|
{
|
|
me->GetMotionMaster()->Clear(false);
|
|
me->RemoveAura(SPELL_SNEAK_RANK_1_1);
|
|
me->RemoveAura(SPELL_SNEAK_RANK_1_2);
|
|
}
|
|
|
|
void SpellHit(Unit* caster, SpellInfo const* spell)
|
|
{
|
|
if (spell->Id == SPELL_MARK_OF_ARLOKK_TRIGGER) // Should only hit if line of sight
|
|
me->Attack(caster, true);
|
|
}
|
|
|
|
void JustDied(Unit* /*killer*/)
|
|
{
|
|
if (Unit* arlokk = ObjectAccessor::GetUnit(*me, _instance->GetData64(NPC_ARLOKK)))
|
|
{
|
|
if (arlokk->IsAlive())
|
|
arlokk->GetAI()->SetData(_sideData, 0);
|
|
}
|
|
me->DespawnOrUnsummon(4000);
|
|
}
|
|
|
|
void UpdateAI(uint32 diff)
|
|
{
|
|
if (UpdateVictim())
|
|
{
|
|
DoMeleeAttackIfReady();
|
|
return;
|
|
}
|
|
|
|
_events.Update(diff);
|
|
|
|
while (uint32 eventId = _events.ExecuteEvent())
|
|
{
|
|
switch (eventId)
|
|
{
|
|
case EVENT_ATTACK:
|
|
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0.0f, 100, false))
|
|
me->Attack(target, true);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private:
|
|
int32 _sideData;
|
|
EventMap _events;
|
|
InstanceScript* _instance;
|
|
};
|
|
|
|
CreatureAI* GetAI(Creature* creature) const
|
|
{
|
|
return GetZulGurubAI<npc_zulian_prowlerAI>(creature);
|
|
}
|
|
};
|
|
|
|
/*######
|
|
## go_gong_of_bethekk
|
|
######*/
|
|
|
|
Position const PosSummonArlokk[1] =
|
|
{
|
|
{ -11507.22f, -1628.062f, 41.38264f, 3.159046f }
|
|
};
|
|
|
|
class go_gong_of_bethekk : public GameObjectScript
|
|
{
|
|
public: go_gong_of_bethekk() : GameObjectScript("go_gong_of_bethekk") { }
|
|
|
|
bool OnGossipHello(Player* /*player*/, GameObject* go)
|
|
{
|
|
if (go->GetInstanceScript())
|
|
{
|
|
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
|
go->SendCustomAnim(0);
|
|
go->SummonCreature(NPC_ARLOKK, PosSummonArlokk[0], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 600000);
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
void AddSC_boss_arlokk()
|
|
{
|
|
new boss_arlokk();
|
|
new npc_zulian_prowler();
|
|
new go_gong_of_bethekk();
|
|
}
|