rendered paste body// --- Illidan Encounter Event --- //
// --- Fully scripted by M4ksiu --- //
/* Global Variables */
// Additional stuff
uint32 m_phase[1000000]; // dunno if it's enough (uint32 InstanceID -> 4,294,967,295)
// Events
uint32 DeathEvent[1000000];
#define WALK 0
#define RUN 256
#define FLY 768
// Global settings - comment to disable
#define USE_SHADOW_PRISON // aggroes a lot of mobs/NPCs if they are not friendly to Illidan
// Structs
struct Coords
{
float x;
float y;
float z;
float o;
};
struct Coords SearchPos[]=
{
{ 744.743896f, 270.928619f, 352.996185f, 2.605572f },
{ 742.240051f, 330.404205f, 352.996185f, 3.249600f },
{ 686.947632f, 305.891022f, 353.192383f, 3.096451f },
{ 676.432495f, 266.354828f, 353.264984f, 4.317750f },
{ 674.560974f, 353.792755f, 352.996094f, 1.918359f }
};
/* Effect and Trigger AIs */
/* Door Event Trigger AI - Creature AI Class */
#define CN_DOOR_EVENT_TRIGGER 30001
class DoorEventTriggerAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(DoorEventTriggerAI);
DoorEventTriggerAI(Creature* pCreature) : CreatureAIScript(pCreature)
{
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
_unit->GetAIInterface()->m_moveFly = true;
}
};
/* Demon Fire AI - Creature AI Class */
#define CN_DEMON_FIRE 23069
#define DEMON_FIRE 40029
class DemonFireAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(DemonFireAI);
DemonFireAI(Creature* pCreature) : CreatureAIScript(pCreature)
{
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
_unit->CastSpell(_unit, dbcSpell.LookupEntry(DEMON_FIRE), true);
_unit->GetAIInterface()->disable_melee = true;
_unit->GetAIInterface()->m_canMove = false;
_unit->m_noRespawn = true;
_unit->Despawn(60000, 0);
}
void OnCombatStop(Unit *mTarget)
{
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->SetAIState(STATE_IDLE);
}
};
/* Eye Beam Trigger AI - Creature AI Class */
#define CN_EYE_BEAM_TRIGGER 30000
#define EYE_BLAST 40017
class EyeBeamTriggerAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(EyeBeamTriggerAI);
EyeBeamTriggerAI(Creature* pCreature) : CreatureAIScript(pCreature)
{
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
_unit->GetAIInterface()->SetAIState(STATE_SCRIPTMOVE);
_unit->GetAIInterface()->disable_melee = true;
_unit->GetAIInterface()->m_moveRun = true;
_unit->m_noRespawn = true;
_unit->Despawn(12000, 0);
RegisterAIUpdateEvent(1000);
WallCreating = false;
}
void OnCombatStop(Unit *mTarget)
{
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->SetAIState(STATE_IDLE);
}
void OnDied(Unit * mKiller)
{
RemoveAIUpdateEvent();
}
void AIUpdate()
{
if (WallCreating == false)
{
if (_unit->GetPositionX() == 642.240601f && _unit->GetPositionY() == 297.297180f && _unit->GetPositionZ() == 353.423401f)
_unit->GetAIInterface()->MoveTo(707.019043f, 270.441772f, 352.996063f, 5.953270f);
if (_unit->GetPositionX() == 641.197449f && _unit->GetPositionY() == 314.330963f && _unit->GetPositionZ() == 353.300262f)
_unit->GetAIInterface()->MoveTo(706.592407f, 343.425568f, 352.996124f, 3.659908f);
if (_unit->GetPositionX() == 657.239807f && _unit->GetPositionY() == 256.925568f && _unit->GetPositionZ() == 352.996094f)
_unit->GetAIInterface()->MoveTo(706.593262f, 310.011475f, 353.693848f, 2.506154f);
if (_unit->GetPositionX() == 657.913330f && _unit->GetPositionY() == 353.562775f && _unit->GetPositionZ() == 352.996185f)
_unit->GetAIInterface()->MoveTo(706.751343f, 298.312683f, 353.653809f, 3.436852f);
if (_unit->GetPositionX() == 707.019043f && _unit->GetPositionY() == 270.441772f && _unit->GetPositionZ() == 352.996063f)
_unit->GetAIInterface()->MoveTo(642.240601f, 297.297180f, 353.423401f, 5.953270f);
if (_unit->GetPositionX() == 706.592407f && _unit->GetPositionY() == 343.425568f && _unit->GetPositionZ() == 352.996124f)
_unit->GetAIInterface()->MoveTo(641.197449f, 314.330963f, 353.300262f, 3.659908f);
if (_unit->GetPositionX() == 706.593262f && _unit->GetPositionY() == 310.011475f && _unit->GetPositionZ() == 353.693848f)
_unit->GetAIInterface()->MoveTo(657.239807f, 256.925568f, 352.996094f, 2.506154f);
if (_unit->GetPositionX() == 706.751343f && _unit->GetPositionY() == 298.312683f && _unit->GetPositionZ() == 353.653809f)
_unit->GetAIInterface()->MoveTo(657.913330f, 353.562775f, 352.996185f, 3.436852f);
WallCreating = true;
}
_unit->CastSpell(_unit, dbcSpell.LookupEntry(EYE_BLAST), true);
}
protected:
bool WallCreating;
};
/* Flame Crash Effect AI - Creature AI Class */
#define CN_FLAME_CRASH 23336
#define FLAME_CRASH_EFFECT 40836
class FlameCrashAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(FlameCrashAI);
FlameCrashAI(Creature* pCreature) : CreatureAIScript(pCreature)
{
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
_unit->CastSpell(_unit, dbcSpell.LookupEntry(FLAME_CRASH_EFFECT), true);
_unit->GetAIInterface()->disable_melee = true;
_unit->GetAIInterface()->m_canMove = false;
_unit->m_noRespawn = true;
_unit->Despawn(120000, 0);
}
void OnCombatStop(Unit *mTarget)
{
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->SetAIState(STATE_IDLE);
}
};
/* Blaze Effect AI - Creature AI Class */
#define CN_BLAZE 23259
#define BLAZE_EFFECT 40610
class BlazeAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(BlazeAI);
BlazeAI(Creature* pCreature) : CreatureAIScript(pCreature)
{
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
_unit->CastSpell(_unit, dbcSpell.LookupEntry(BLAZE_EFFECT), true);
_unit->GetAIInterface()->disable_melee = true;
_unit->GetAIInterface()->m_canMove = false;
_unit->m_noRespawn = true;
_unit->Despawn(60000, 0);
}
void OnCombatStop(Unit *mTarget)
{
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->SetAIState(STATE_IDLE);
}
};
/* Misc Creature AIs */
/* Flame of Azzinoth AI - Creature AI Class */
#define CN_FLAME_OF_AZZINOTH 22997
#define BLAZE 40637 // this one just summons mob that will trigger that fire cloud - doesn't spawn mob
#define FLAME_BLAST 40631
#define FOA_ENRAGE 40683 // 40683 or 40743
#define CHAOS_CHARGE 40497 // CHAOS_CHARGE 40497 CHARGE 40602
class FlameOfAzzinothAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(FlameOfAzzinothAI);
SP_AI_Spell spells[4];
bool m_spellcheck[4];
FlameOfAzzinothAI(Creature* pCreature) : CreatureAIScript(pCreature)
{
nrspells = 2;
for (int i = 0; i < nrspells; i++)
{
m_spellcheck[i] = false;
spells[i].casttime = 0;
}
spells[0].info = dbcSpell.LookupEntry(BLAZE);
spells[0].targettype = TARGET_SELF;
spells[0].instant = true;
spells[0].cooldown = 30;
spells[0].perctrigger = 7.0f;
spells[0].attackstoptimer = 1000;
spells[1].info = dbcSpell.LookupEntry(FLAME_BLAST);
spells[1].targettype = TARGET_VARIOUS;
spells[1].instant = true;
spells[1].cooldown = 15;
spells[1].perctrigger = 13.0f;
spells[1].attackstoptimer = 1000;
spells[2].info = dbcSpell.LookupEntry(CHAOS_CHARGE);
spells[2].targettype = TARGET_ATTACKING;
spells[2].instant = true;
spells[3].info = dbcSpell.LookupEntry(FOA_ENRAGE);
spells[3].targettype = TARGET_SELF;
spells[3].instant = true;
_unit->m_noRespawn = true;
Enrage = false;
}
void OnCombatStart(Unit* mTarget)
{
for (int i = 0; i < nrspells; i++)
spells[i].casttime = 0;
RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME));
}
void OnCombatStop(Unit *mTarget)
{
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->SetAIState(STATE_IDLE);
RemoveAIUpdateEvent();
}
void OnDied(Unit * mKiller)
{
RemoveAIUpdateEvent();
}
void AIUpdate()
{
if (Enrage == true)
{
_unit->CastSpell(_unit, spells[3].info, spells[3].instant);
Enrage = false;
return;
}
if (_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget() != NULL)
{
Unit *target = NULL;
target = _unit->GetAIInterface()->GetNextTarget();
if (_unit->GetDistance2dSq(target) >= 225.0f && _unit->GetDistance2dSq(target) <= 1225 && rand()%5 == 0) // I must test this value (15-35yards for now)
{
_unit->CastSpell(target, spells[2].info, spells[2].instant);
Enrage = true;
return;
}
}
float val = (float)RandomFloat(100.0f);
SpellCast(val);
}
void SpellCast(float val)
{
if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
{
float comulativeperc = 0;
Unit *target = NULL;
for(int i=0;i<nrspells;i++)
{
if(!spells[i].perctrigger) continue;
if(m_spellcheck[i])
{
target = _unit->GetAIInterface()->GetNextTarget();
switch(spells[i].targettype)
{
case TARGET_SELF:
case TARGET_VARIOUS:
_unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
case TARGET_ATTACKING:
_unit->CastSpell(target, spells[i].info, spells[i].instant); break;
case TARGET_DESTINATION:
_unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
}
m_spellcheck[i] = false;
return;
}
uint32 t = (uint32)time(NULL);
if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger) && t > spells[i].casttime)
{
_unit->setAttackTimer(spells[i].attackstoptimer, false);
spells[i].casttime = t + spells[i].cooldown;
m_spellcheck[i] = true;
}
comulativeperc += spells[i].perctrigger;
}
}
}
protected:
int nrspells;
bool Enrage;
};
/* Akama AI - Creature Gossip Class */
#define SendQuickMenu(textid) objmgr.CreateGossipMenuForPlayer(&Menu, pCreature->GetGUID(), textid, plr); \
Menu->SendTo(plr);
class SCRIPT_DECL AkamaGossip : public GossipScript
{
public:
void GossipHello(Object* pObject, Player* plr, bool AutoSend)
{
GossipMenu *Menu;
Creature *Akama = (Creature*)(pObject);
if (Akama == NULL)
return;
if (Akama->GetAIInterface()->getCurrentWaypoint() >= 10)
{
objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 229902, plr);
Menu->AddItem( 0, "We're ready to face Illidan.", 2);
}
else
{
objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 229901, plr);
Menu->AddItem( 0, "I'm ready, Akama.", 1);
}
if(AutoSend)
Menu->SendTo(plr);
}
void GossipSelectOption(Object* pObject, Player* plr, uint32 Id, uint32 IntId, const char * EnteredCode)
{
Creature *Akama = (Creature*)(pObject);
if (Akama == NULL)
return;
switch (IntId)
{
case 0:
GossipHello(pObject, plr, true);
break;
case 1:
Akama->SetUInt32Value(UNIT_NPC_FLAGS, 0);
Akama->GetAIInterface()->StopMovement(0);
Akama->GetAIInterface()->SetAIState(STATE_SCRIPTMOVE);
Akama->GetAIInterface()->setMoveType(MOVEMENTTYPE_WANTEDWP);
Akama->GetAIInterface()->setWaypointToMove(1);
break;
case 2:
Akama->SetUInt32Value(UNIT_NPC_FLAGS, 0);
Akama->GetAIInterface()->StopMovement(0);
Akama->GetAIInterface()->SetAIState(STATE_SCRIPTMOVE);
Akama->GetAIInterface()->setMoveType(MOVEMENTTYPE_WANTEDWP);
Akama->GetAIInterface()->setWaypointToMove(17);
break;
}
}
void Destroy()
{
delete this;
}
};
/* Akama AI - Creature AI Class */
#define CN_AKAMA 22990
#define HEALING_POTION 40535
#define BLESSING_OF_KINGS 20217
#define AKAMA_DESPAWN 41242
// Door Event Spells
#define AKAMA_DOOR_FAIL 41271
#define AKAMA_DOOR_OPEN 41268
#define DEATHSWORN_DOOR_OPEN 41269
#define GATE_FAILURE 10390
static Coords ToIllidan[] =
{
{ },
{ 660.248596f, 330.695679f, 271.688110f, 1.243284f },
{ 671.172241f, 353.273193f, 271.689453f, 1.022600f },
{ 694.227783f, 379.461365f, 271.792145f, 6.232135f },
{ 724.159973f, 373.263275f, 282.614349f, 5.324218f },
{ 747.034973f, 335.668274f, 307.047150f, 4.972365f },
{ 755.477234f, 304.194580f, 312.167328f, 6.276120f },
{ 771.809753f, 303.744873f, 313.563507f, 6.265894f },
{ 778.550232f, 304.515198f, 318.818542f, 0.002354f },
{ 789.564697f, 304.493652f, 319.759583f, 6.248631f },
{ 799.598389f, 295.776642f, 319.760040f, 4.687257f },
{ 799.054016f, 288.826660f, 320.030334f, 4.563174f },
{ 794.595459f, 262.302856f, 341.463715f, 4.500343f },
{ 794.396973f, 256.420471f, 341.463715f, 4.557680f },
{ 783.355957f, 250.460892f, 341.463776f, 3.746361f },
{ 764.988098f, 238.561462f, 353.646484f, 3.324606f },
{ 749.337463f, 236.288681f, 352.997223f, 1.633631f },
{ 751.941528f, 304.626221f, 352.996124f, 3.128243f },
{ 747.236511f, 304.922913f, 352.996155f, 6.278462f },
{ 747.834106f, 362.513977f, 352.996155f, 1.604554f }
};
class AkamaAI : public CreatureAIScript
{
public:
friend class AkamaGossip;
ADD_CREATURE_FACTORY_FUNCTION(AkamaAI);
SP_AI_Spell spells[3];
bool m_spellcheck[3];
AkamaAI(Creature* pCreature) : CreatureAIScript(pCreature)
{
for (int i = 1; i < 20; i++)
{
_unit->GetAIInterface()->addWayPoint(CreateWaypoint(i, 0, RUN));
}
nrspells = 1;
for (int i = 0; i < nrspells; i++)
{
m_spellcheck[i] = false;
spells[i].casttime = 0;
}
spells[0].info = dbcSpell.LookupEntry(BLESSING_OF_KINGS);
spells[0].targettype = TARGET_SELF;
spells[0].instant = true;
spells[0].cooldown = 600; // 10 min
spells[0].perctrigger = 15.0f;
spells[0].attackstoptimer = 1000;
spells[1].info = dbcSpell.LookupEntry(HEALING_POTION);
spells[1].targettype = TARGET_SELF;
spells[1].instant = true;
spells[1].cooldown = 0;
spells[1].perctrigger = 0.0f;
spells[1].attackstoptimer = 1000;
spells[2].info = dbcSpell.LookupEntry(AKAMA_DESPAWN);
spells[2].targettype = TARGET_SELF;
spells[2].instant = false;
spells[2].cooldown = 0;
spells[2].perctrigger = 0.0f;
spells[2].attackstoptimer = 1000;
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
m_phase[_unit->GetInstanceID()] = 0;
EventChapter = 0;
SoundLimiter = 0;
EventTimer = 0;
Udalo = Olum = NULL;
if (!DeathEvent[_unit->GetInstanceID()])
_unit->SetUInt32Value(UNIT_NPC_FLAGS, 1);
else
{
_unit->SetUInt32Value(UNIT_NPC_FLAGS, 0);
RegisterAIUpdateEvent(1000);
EventChapter = 2;
}
}
void OnCombatStart(Unit* mTarget)
{
for (int i = 0; i < nrspells; i++)
spells[i].casttime = 0;
SoundLimiter = 0;
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);
RegisterAIUpdateEvent(1000);
}
void OnCombatStop(Unit *mTarget)
{
if (m_phase[_unit->GetInstanceID()] > 0)
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->SetAIState(STATE_IDLE);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
//RemoveAIUpdateEvent();
}
void OnTargetDied(Unit* mTarget)
{
if (_unit->GetHealthPct() > 0)
{
int RandomSpeach = rand()%2;
switch (RandomSpeach)
{
case 0:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Illidan will pay!");
_unit->PlaySoundToSet(11381);
break;
case 1:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "One step closer!");
_unit->PlaySoundToSet(11382);
break;
}
}
}
void OnDied(Unit * mKiller)
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Fight on friends! Kill him and end the curse on my people!"); // not sure
_unit->PlaySoundToSet(11391);
RemoveAIUpdateEvent();
EventTimer = 0;
}
void AIUpdate()
{
switch (EventChapter)
{
case 0:
WayToIllidan();
break;
case 1:
FightWithIllidan();
break;
case 2:
EncounterEnd();
break;
}
}
void WayToIllidan()
{
if (_unit->GetAIInterface()->getCurrentWaypoint() == 6 && EventTimer > 0)
{
GameObject* Gate = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(774.7f, 304.6f, 314.85f, 185905);
Unit* DoorTrigger = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(771.5f, 304.7f, 319.0f, CN_DOOR_EVENT_TRIGGER);
if (Gate == NULL)
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "It's strange that Illidan doesn't protect himself against intruders." );
_unit->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0);
_unit->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_WANTEDWP);
_unit->GetAIInterface()->setWaypointToMove(7);
if (Udalo != NULL)
{
Udalo->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0);
Udalo->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
Udalo = NULL;
}
if (Olum != NULL)
{
Olum->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0);
Olum->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
Olum = NULL;
}
RemoveAIUpdateEvent();
EventTimer = 0;
return;
}
switch (EventTimer)
{
case 2:
_unit->SetFacing(6.248631f);
break;
case 6:
_unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "The door is all that stands between us and the Betrayer. Stand aside, friends." );
_unit->Emote(EMOTE_ONESHOT_TALK);
break;
case 10: // here will be first try to break door (Akama himself only)
if (DoorTrigger != NULL)
{
_unit->CastSpell(DoorTrigger, dbcSpell.LookupEntry(AKAMA_DOOR_FAIL), false);
_unit->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, DoorTrigger->GetGUID());
_unit->SetUInt32Value(UNIT_CHANNEL_SPELL, AKAMA_DOOR_FAIL);
}
break;
case 19: // here we will stop casting spell on door
_unit->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0);
_unit->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
break;
case 20:
_unit->Emote(EMOTE_ONESHOT_NO);
_unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "I cannot do this alone..." );
break;
case 26: // summoning two spirits to help Akama with breaking doors
Udalo = _unit->GetMapMgr()->GetInterface()->SpawnCreature(23410, 751.884705f, 311.270050f, 312.121185f, 0.047113f, true, false, 0, 0);
Olum = _unit->GetMapMgr()->GetInterface()->SpawnCreature(23411, 751.687744f, 297.408600f, 312.124817f, 0.054958f, true, false, 0, 0);
if (Udalo != NULL)
{
Udalo->GetAIInterface()->SetAllowedToEnterCombat(false);
Udalo->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9);
Udalo->m_noRespawn = true;
Udalo->Despawn(45000, 0);
}
if (Olum != NULL)
{
Olum->GetAIInterface()->SetAllowedToEnterCombat(false);
Olum->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9);
Olum->m_noRespawn = true;
Olum->Despawn(45000, 0);
}
break;
case 27:
if (Udalo != NULL)
Udalo->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "You are not alone, Akama." );
break;
case 33:
if (Olum != NULL)
Olum->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Your people will always be with you." );
break;
case 38: // Akama starts casting his spell again with both spirits
if (DoorTrigger != NULL)
{
_unit->CastSpell(DoorTrigger, dbcSpell.LookupEntry(AKAMA_DOOR_OPEN), false);
_unit->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, DoorTrigger->GetGUID());
_unit->SetUInt32Value(UNIT_CHANNEL_SPELL, AKAMA_DOOR_OPEN);
}
break;
case 39:
if (DoorTrigger != NULL)
{
if (Udalo != NULL)
{
Udalo->CastSpell(DoorTrigger, dbcSpell.LookupEntry(DEATHSWORN_DOOR_OPEN), false);
Udalo->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, DoorTrigger->GetGUID());
Udalo->SetUInt32Value(UNIT_CHANNEL_SPELL, DEATHSWORN_DOOR_OPEN);
}
if (Olum != NULL)
{
Olum->CastSpell(DoorTrigger, dbcSpell.LookupEntry(DEATHSWORN_DOOR_OPEN), false);
Olum->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, DoorTrigger->GetGUID());
Olum->SetUInt32Value(UNIT_CHANNEL_SPELL, DEATHSWORN_DOOR_OPEN);
}
}
break;
case 48: // Door has been broken and channel stopped
Gate->SetUInt32Value(GAMEOBJECT_STATE, 0);
if (DoorTrigger != NULL)
{
DoorTrigger->CastSpell(_unit, dbcSpell.LookupEntry(GATE_FAILURE), true);
}
break;
case 49:
_unit->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0);
_unit->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
if (Udalo != NULL)
{
Udalo->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0);
Udalo->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
}
if (Olum != NULL)
{
Olum->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0);
Olum->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
}
break;
case 52:
_unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "I thank you for your aid, my brothers. Our people will be redeemed!" );
_unit->Emote(EMOTE_ONESHOT_SALUTE);
break;
case 55:
if (Udalo != NULL)
Udalo->Emote(EMOTE_ONESHOT_SALUTE);
if (Olum != NULL)
Olum->Emote(EMOTE_ONESHOT_SALUTE);
Udalo = NULL;
Olum = NULL;
break;
case 58:
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_WANTEDWP);
_unit->GetAIInterface()->setWaypointToMove(7);
RemoveAIUpdateEvent();
break;
}
EventTimer++;
if (EventTimer > 58)
EventTimer = 0;
}
if (EventTimer > 0 && _unit->GetAIInterface()->getCurrentWaypoint() == 16)
{
EventTimer++;
switch (EventTimer)
{
case 2:
_unit->PlaySoundToSet(11388);
_unit->SetFacing(2.113512f);
break;
case 17:
_unit->SetUInt32Value(UNIT_NPC_FLAGS, 1);
RemoveAIUpdateEvent();
EventTimer = 0;
break;
}
}
if (EventTimer > 0 && _unit->GetAIInterface()->getCurrentWaypoint() == 17 && m_phase[_unit->GetInstanceID()] == 0)
{
Illidan = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(704.539001f, 305.282013f, 353.919006f, 22917);
if (Illidan == NULL || !Illidan->isAlive())
{
RemoveAIUpdateEvent();
_unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Not this time my friends." );
_unit->CastSpell(_unit, spells[2].info, spells[2].instant);
_unit->Despawn(0,0);
EventTimer = 0;
return;
}
switch(EventTimer)
{
case 1:
_unit->SetFacing(3.126680f);
break;
case 2:
Illidan->RemoveAura(39656);
break;
case 3:
Illidan->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Akama... your duplicity is hardly surprising. I should have slaughtered you and your malformed brethren long ago.");
Illidan->PlaySoundToSet(11463);
break;
case 7:
Illidan->Emote(EMOTE_ONESHOT_QUESTION);
break;
case 12:
Illidan->Emote(EMOTE_ONESHOT_QUESTION);
break;
case 15:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "We've come to end your reign, Illidan. My people and all of Outland shall be free!");
_unit->PlaySoundToSet(11389);
_unit->Emote(EMOTE_ONESHOT_POINT);
break;
case 18:
_unit->Emote(EMOTE_ONESHOT_TALK);
break;
case 22:
_unit->Emote(EMOTE_ONESHOT_SALUTE);
break;
case 25:
Illidan->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Boldly said. But I remain unconvinced.");
Illidan->PlaySoundToSet(11464);
Illidan->Emote(EMOTE_ONESHOT_QUESTION);
break;
case 28:
Illidan->Emote(EMOTE_ONESHOT_QUESTION);
break;
case 32:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "The time has come! The moment is at hand!");
_unit->PlaySoundToSet(11380);
_unit->Emote(EMOTE_ONESHOT_SHOUT);
break;
case 34:
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);
_unit->Emote(EMOTE_ONESHOT_ROAR);
break;
case 36:
Illidan->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "You are not prepared!");
Illidan->PlaySoundToSet(11466);
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_READY1H);
Illidan->Emote(EMOTE_ONESHOT_CUSTOMSPELL05);
break;
case 38:
Illidan->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);
break;
case 40:
GameObject* RightGate = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(745.07f, 241.802f, 354.292f, 200000);
GameObject* LeftGate = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(744.829f, 369.276f, 354.324f, 200001);
if (RightGate != NULL)
RightGate->SetUInt32Value(GAMEOBJECT_STATE, 1);
if (LeftGate != NULL)
LeftGate->SetUInt32Value(GAMEOBJECT_STATE, 1);
_unit->GetAIInterface()->SetAllowedToEnterCombat(true);
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->SetAIState(STATE_IDLE);
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, 0);
_unit->GetAIInterface()->m_canMove = true;
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
_unit->GetAIInterface()->setWaypointToMove(0);
Illidan->GetAIInterface()->SetAllowedToEnterCombat(true);
Illidan->SetUInt64Value(UNIT_FIELD_FLAGS, 0);
Illidan->GetAIInterface()->m_canMove = true;
RemoveAIUpdateEvent();
_unit->GetAIInterface()->AttackReaction(Illidan, 1, 0);
Unit *IllidanTarget = NULL;
IllidanTarget = FindTarget();
if (IllidanTarget == NULL)
{
IllidanTarget = _unit;
}
Illidan->GetAIInterface()->AttackReaction(IllidanTarget, 500, 0);
EventChapter = 1;
break;
}
EventTimer++;
if (EventTimer > 40)
EventTimer = 0;
}
}
void FightWithIllidan()
{
SoundLimiter++;
if (_unit->GetHealthPct() <= 15 && _unit->GetAIInterface()->GetNextTarget() != NULL)
{
if (SoundLimiter >= 15)
{
int RandomSpeach = rand()%2;
switch (RandomSpeach)
{
case 0:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "I will not last much longer!");
_unit->PlaySoundToSet(11385);
break;
case 1:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "No! Not yet!");
_unit->PlaySoundToSet(11386);
break;
}
SoundLimiter = 0;
}
if (_unit->GetAIInterface()->GetNextTarget()->GetTypeId() == TYPEID_UNIT)
{
Creature *Target = NULL;
Target = (Creature*)_unit->GetAIInterface()->GetNextTarget();
if (Target != NULL && Target->GetEntry() == 22917)
_unit->CastSpell(_unit, spells[1].info, spells[1].instant);
}
}
if ((_unit->GetAIInterface()->GetNextTarget() != NULL || EventTimer > 7) && _unit->GetAIInterface()->getCurrentWaypoint() < 18 && m_phase[_unit->GetInstanceID()] != 0)
{
if (_unit->GetAIInterface()->GetAllowedToEnterCombat() == true && EventTimer < 7) // && Illidan && Illidan->GetHealthPct() > 85)
{
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_READY1H);
float val = (float)RandomFloat(100.0f);
SpellCast(val);
}
if ((Illidan == NULL || !Illidan->isAlive()) && EventTimer <= 7)
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Not this time my friends.");
_unit->CastSpell(_unit, spells[2].info, spells[2].instant);
_unit->Despawn(0,0);
}
if ((Illidan != NULL && Illidan->isAlive() && Illidan->GetHealthPct() <= 85 && EventTimer <= 7) || EventTimer > 7)
{
switch (EventTimer)
{
case 0:
Illidan->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Come, my minions. Deal with this traitor as he deserves!");
Illidan->PlaySoundToSet(11465);
break;
case 7:
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9);
_unit->GetAIInterface()->SetAIState(STATE_IDLE);
_unit->GetAIInterface()->SetNextTarget(NULL);
_unit->GetAIInterface()->WipeTargetList();
_unit->GetAIInterface()->WipeHateList();
_unit->GetAIInterface()->disable_melee = true;
_unit->GetAIInterface()->m_canMove = false;
Illidan->GetAIInterface()->RemoveThreatByPtr(_unit); // Akama will stuck in place anyway if alone in combat with Illidan
break;
case 8:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "I will deal with these mongrels! Strike now, friends! Strike at the Betrayer!");
_unit->PlaySoundToSet(11390);
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
break;
case 9:
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_READY1H);
break;
case 10:
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
break;
case 11:
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
_unit->Emote(EMOTE_ONESHOT_EXCLAMATION);
break;
case 13:
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_READY1H);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);
break;
case 15:
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
_unit->GetAIInterface()->m_canMove = true;
_unit->GetAIInterface()->StopMovement(0);
_unit->GetAIInterface()->SetAIState(STATE_SCRIPTMOVE);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_WANTEDWP);
_unit->GetAIInterface()->setWaypointToMove(18);
RemoveAIUpdateEvent();
//_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
break;
}
EventTimer++;
if (EventTimer > 15)
EventTimer = 0;
}
}
}
void EncounterEnd()
{
if (m_phase[_unit->GetInstanceID()] == 0 && DeathEvent[_unit->GetInstanceID()] >= 40)
{
if (DeathEvent[_unit->GetInstanceID()] <= 41)
{
Unit *Maiev = NULL;
for (int i = 0; i < 5; i++)
{
Maiev = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(SearchPos[i].x, SearchPos[i].y, SearchPos[i].z, 23197);
if (Maiev != NULL && Maiev->isAlive())
{
MposX = Maiev->GetPositionX();
MposY = Maiev->GetPositionY();
MposZ = Maiev->GetPositionZ();
MposO = Maiev->GetOrientation();
break;
}
}
// Akama is despawned if he can't find Maiev anywhere (better than going to position x = 0.0f y = 0.0f and z = 0.0f (cells too small)
if (Maiev == NULL)
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Not this time my friends.");
_unit->CastSpell(_unit, spells[2].info, spells[2].instant);
_unit->Despawn(0,0);
}
}
if (_unit->GetPositionX() == MposX && _unit->GetPositionY() == MposY && _unit->GetPositionZ() == MposZ && DeathEvent[_unit->GetInstanceID()] < 44)
DeathEvent[_unit->GetInstanceID()] = 44;
if (DeathEvent[_unit->GetInstanceID()] == 42)
{
_unit->GetAIInterface()->m_moveRun = true;
_unit->GetAIInterface()->MoveTo(MposX, MposY, MposZ, MposO);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(1000);
DeathEvent[_unit->GetInstanceID()] = 43;
//_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_READY1H); // dunno why this emote sometimes bugs facing
//_unit->GetAIInterface()->SetNextTarget(Illidan);
}
if (DeathEvent[_unit->GetInstanceID()] >= 45)
{
switch (DeathEvent[_unit->GetInstanceID()])
{
case 45:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "The Light will fill these dismal halls once again. I swear it.");
_unit->PlaySoundToSet(11387);
Illidan = NULL;
Illidan = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(_unit->GetPositionX(), _unit->GetPositionY(), _unit->GetPositionZ(), 22917);
if (Illidan != NULL)
_unit->GetAIInterface()->SetNextTarget(Illidan);
_unit->Emote(EMOTE_ONESHOT_TALK);
break;
case 49:
_unit->Emote(EMOTE_ONESHOT_SALUTE);
break;
case 53:
DeathEvent[_unit->GetInstanceID()] = 0;
_unit->CastSpell(_unit, spells[2].info, spells[2].instant);
_unit->Despawn(0,0);
break;
}
}
if (DeathEvent[_unit->GetInstanceID()] >= 44)
DeathEvent[_unit->GetInstanceID()]++;
}
}
void SpellCast(float val)
{
if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
{
float comulativeperc = 0;
Unit *target = NULL;
for(int i=0;i<nrspells;i++)
{
if(!spells[i].perctrigger) continue;
if(m_spellcheck[i])
{
target = _unit->GetAIInterface()->GetNextTarget();
switch(spells[i].targettype)
{
case TARGET_SELF:
case TARGET_VARIOUS:
_unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
case TARGET_ATTACKING:
_unit->CastSpell(target, spells[i].info, spells[i].instant); break;
case TARGET_DESTINATION:
_unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
}
m_spellcheck[i] = false;
return;
}
uint32 t = (uint32)time(NULL);
if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger) && t > spells[i].casttime)
{
_unit->setAttackTimer(spells[i].attackstoptimer, false);
spells[i].casttime = t + spells[i].cooldown;
m_spellcheck[i] = true;
}
comulativeperc += spells[i].perctrigger;
}
}
}
void OnReachWP(uint32 iWaypointId, bool bForwards)
{
switch (iWaypointId)
{
case 6:
case 16:
case 17:
RegisterAIUpdateEvent(1000);
EventTimer = 1;
break;
case 19:
_unit->Despawn(0, 0);
break;
case 20:
DeathEvent[_unit->GetInstanceID()] = 49;
break;
default:
{
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_WANTEDWP);
_unit->GetAIInterface()->setWaypointToMove(iWaypointId+1);
}
}
}
inline WayPoint* CreateWaypoint(int id, uint32 waittime, uint32 flags)
{
WayPoint * wp = _unit->CreateWaypointStruct();
wp->id = id;
wp->x = ToIllidan[id].x;
wp->y = ToIllidan[id].y;
wp->z = ToIllidan[id].z;
wp->o = ToIllidan[id].o;
wp->waittime = waittime;
wp->flags = flags;
wp->forwardemoteoneshot = 0;
wp->forwardemoteid = 0;
wp->backwardemoteoneshot = 0;
wp->backwardemoteid = 0;
wp->forwardskinid = 0;
wp->backwardskinid = 0;
return wp;
}
// A bit rewritten FindTarget function
Unit* FindTarget()
{
Unit* target = NULL;
float distance = 70.0f;
float z_diff;
Unit *pUnit;
float dist;
for (std::set<Player*>::iterator itr = _unit->GetInRangePlayerSetBegin(); itr != _unit->GetInRangePlayerSetEnd(); itr++)
{
pUnit = static_cast<Unit*>((*itr));
if(pUnit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FEIGN_DEATH))
continue;
z_diff = fabs(_unit->GetPositionZ() - pUnit->GetPositionZ());
if(z_diff > 5.0f)
continue;
if(pUnit->m_invisible)
continue;
if(!pUnit->isAlive())
continue;
dist = Illidan->GetDistance2dSq(pUnit);
if(dist > distance*distance)
continue;
distance = dist;
target = pUnit;
}
return target;
}
protected:
float MposX, MposY, MposZ, MposO;
uint32 SoundLimiter;
uint32 EventChapter;
uint32 EventTimer;
Creature *Udalo;
Creature *Olum;
Unit *Illidan;
int nrspells;
};
/* Maiev AI - Creature AI Class */
#define CN_MAIEV 23197
//#define TELEPORT_MAIEV 41221
#define TELEPORT 34673 // 34673, 41992
class MaievAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(MaievAI);
SP_AI_Spell spells[1];
MaievAI(Creature* pCreature) : CreatureAIScript(pCreature)
{
spells[0].info = dbcSpell.LookupEntry(TELEPORT);
spells[0].targettype = TARGET_SELF;
spells[0].instant = true;
spells[0].cooldown = 0;
spells[0].perctrigger = 0.0f;
spells[0].attackstoptimer = 0;
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
SoundTimer = 0;
RegisterAIUpdateEvent(250);
}
void OnCombatStart(Unit* mTarget)
{
//RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME));
//_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);
}
void OnCombatStop(Unit *mTarget)
{
//_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
//_unit->GetAIInterface()->SetAIState(STATE_IDLE);
//_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
//RemoveAIUpdateEvent();
}
void OnDied(Unit * mKiller)
{
RemoveAIUpdateEvent();
SoundTimer = 0;
}
void OnDamageTaken(Unit *mAttacker, float fAmount)
{
_unit->SetUInt32Value(UNIT_FIELD_HEALTH, _unit->GetUInt32Value(UNIT_FIELD_MAXHEALTH));
}
void AIUpdate()
{
_unit->SetUInt32Value(UNIT_FIELD_HEALTH, _unit->GetUInt32Value(UNIT_FIELD_MAXHEALTH));
Unit *Illidan = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(_unit->GetPositionX(), _unit->GetPositionY(), _unit->GetPositionZ(), 22917);
if (DeathEvent[_unit->GetInstanceID()] == 0)
{
if (_unit->GetAIInterface()->GetNextTarget() != NULL && _unit->GetAIInterface()->m_canMove == true)
SoundTimer++;
float SayNaisha = (float)RandomFloat(100.0f);
if ((SayNaisha < 2.5f && SoundTimer >= 100 && SoundTimer < 1330) || SoundTimer == 1361 || SoundTimer > 1400)
{
uint32 RandText;
if (SoundTimer != 1361)
RandText = rand()%3;
if (SoundTimer == 1361)
RandText = rand()%2;
switch (RandText) // Not sure if those both should be here, but couldn't find any relation when those are said on blizz
{
case 0:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Bleed as I have bled!"); // not sure
_unit->PlaySoundToSet(11494);
SoundTimer = 0;
break;
case 1:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "That is for Naisha!");
_unit->PlaySoundToSet(11493);
SoundTimer = 0;
break;
case 2:
if (Illidan != NULL)
{
Illidan->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Feel the hatred of ten thousand years!");
Illidan->PlaySoundToSet(11470);
SoundTimer = 1337;
}break;
}
}
}
if (DeathEvent[_unit->GetInstanceID()] > 0)
{
if ((DeathEvent[_unit->GetInstanceID()] <= 25 && Illidan != NULL) || (DeathEvent[_unit->GetInstanceID()] > 25))
{
switch (DeathEvent[_unit->GetInstanceID()])
{
case 1:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Ah, it is finished. You are beaten."); // not sure
_unit->PlaySoundToSet(11496);
Illidan->Emote(EMOTE_ONESHOT_CUSTOMSPELL06);
if(Illidan->GetCurrentSpell() != NULL)
Illidan->GetCurrentSpell()->cancel();
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(1000);
break;
case 2:
Illidan->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_CUSTOMSPELL07);
_unit->GetAIInterface()->SetNextTarget(Illidan);
break;
case 5:
Illidan->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "You have won... Maiev. But the huntress... is nothing without the hunt. You... are nothing... without me.");
Illidan->PlaySoundToSet(11478);
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
//MaievWeaponOff();
break;
case 25:{
GameObject* RightGate = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(745.07f, 241.802f, 354.292f, 200000);
GameObject* LeftGate = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(744.829f, 369.276f, 354.324f, 200001);
if (RightGate != NULL)
RightGate->SetUInt32Value(GAMEOBJECT_STATE, 0);
if (LeftGate != NULL)
LeftGate->SetUInt32Value(GAMEOBJECT_STATE, 0);
Illidan->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
Illidan->SetUInt32Value(UNIT_FIELD_HEALTH,0);
Illidan->setDeathState(JUST_DIED);
}break;
case 30:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "He's right. I feel nothing. I am nothing.");
_unit->PlaySoundToSet(11497);
break;
case 39:
_unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_AKAMA, ToIllidan[19].x, ToIllidan[19].y, ToIllidan[19].z, ToIllidan[19].o, true, false, 0, 0); // we have one Akama already spawned so we don't need another one =/ (still it's freakin' workaround -.-')
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Farewell, champions.");
_unit->PlaySoundToSet(11498);
break;
case 40:
_unit->CastSpell(_unit, dbcSpell.LookupEntry(TELEPORT), true);
break;
case 41:
RemoveAIUpdateEvent();
_unit->Despawn(0,0);
break;
}
if (DeathEvent[_unit->GetInstanceID()] <= 41)
DeathEvent[_unit->GetInstanceID()]++;
}
else
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Farewell, champions.");
_unit->PlaySoundToSet(11498);
_unit->Despawn(0,0);
}
}
}
protected:
uint32 SoundTimer;
};
/* Illidan Stormrage AI - Creature AI Class */
#define CN_ILLIDAN_STORMRAGE 22917
// Normal Form Spells
#define SHEAR 41032 // +
#define DRAW_SOUL 40904 // +
#define FLAME_CRASH 40832 // +
#define MORTAL_STRIKE 37335 // +
// Demon Forms
#define DEMON_FORM1 40511 // +
#define DEMON_FORM2 40398 // +
#define DEMON_FORM3 40510 // +
// Demon Form Spells
#define SHADOW_BLAST 41078 // +
#define SUMMON_DEMON 41117 // - Core Support
#define FLAME_BURST 41131 // ? Haven't Tried // 41126 is the right one, but it's spell that needs to be scripted
// Illidan's Glaive spells
#define SUMMON_GLAIVE 41466
#define GLAIVE_RETURNS 39873
#define THROW_GLAIVE1 39635
#define THROW_GLAIVE2 39849
// Phase 2 Spells
#define DEMON_FORM 40506
#define AURA_OF_DREAD 41142
#define FIREBALL 40598 // +
#define DARK_BARRAGE 40585 // ? Haven't Tried
#define SUMMON_TEAR_OF_AZZINOTH 39855 // +
#define EYE_BLAST1 39908
#define EYE_BLAST2 40017
#define TEAR_OF_AZZINOTH_CHANNEL 39857
// Phase 3 Spells
#define AGONIZING_FLAMES 40932 // ? Haven't Tried (Before Demon Form!)
// Phase 4 Spells
// Phase 5 Spells
#define ENRAGE 34971 // +
// Other spells
#define SHADOW_PRISON 40647 // +
#define SKULL_INTRO 39656 // + Works with RemoveAura
#define SUMMON_PARASITIC_SHADOWFIENDS 41915 // ? Haven't Tried
#define PARASITIC_SHADOWFIEND1 41914 // ? Haven't Tried
#define PARASITIC_SHADOWFIEND2 41913 // ? Haven't Tried
// Other macros
#define CN_BLADE_OF_AZZINOTH 22996
static Coords ForIllidan[] =
{
{ },
{ 709.783203f, 305.073883f, 362.988770f, 1.546307f }, // Middle pos
{ 678.703735f, 337.249664f, 362.988770f, 4.741172f }, // Eastern pos
{ 679.968384f, 284.618011f, 362.988770f, 1.603503f }, // Western pos
{ 680.798157f, 305.648743f, 353.192200f, 3.196716f } // Land
};
static Coords UnitPos[]=
{
{ 676.717346f, 322.445251f, 354.153320f, 5.732623f }, // Blade 1
{ 677.368286f, 285.374725f, 354.242157f, 5.645614f } // Blade 2
};
class IllidanStormrageAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(IllidanStormrageAI);
SP_AI_Spell spells[15];
bool m_spellcheck[15];
IllidanStormrageAI(Creature* pCreature) : CreatureAIScript(pCreature)
{
_unit->GetAIInterface()->addWayPoint(CreateWaypoint(1, 0, FLY));
_unit->GetAIInterface()->addWayPoint(CreateWaypoint(2, 0, FLY));
_unit->GetAIInterface()->addWayPoint(CreateWaypoint(3, 0, FLY));
_unit->GetAIInterface()->addWayPoint(CreateWaypoint(4, 0, FLY));
nrspells = 5;
for (int i = 0 ; i < nrspells; i++)
{
m_spellcheck[i] = false;
spells[i].casttime = 0;
}
spells[0].info = dbcSpell.LookupEntry(SHEAR);
spells[0].targettype = TARGET_ATTACKING;
spells[0].instant = false;
spells[0].cooldown = 15;
spells[0].perctrigger = 12.0f;
spells[0].attackstoptimer = 1000;
spells[1].info = dbcSpell.LookupEntry(DRAW_SOUL);
spells[1].targettype = TARGET_VARIOUS;
spells[1].instant = false;
spells[1].cooldown = 0;
spells[1].perctrigger = 0.0f; // 6.0f attacks himself too so it can cause crashes if he dies because of his own hit
spells[1].attackstoptimer = 1000;
spells[2].info = dbcSpell.LookupEntry(FLAME_CRASH);
spells[2].targettype = TARGET_DESTINATION;
spells[2].instant = false;
spells[2].cooldown = 25;
spells[2].perctrigger = 12.0f;
spells[2].attackstoptimer = 1000;
spells[3].info = dbcSpell.LookupEntry(MORTAL_STRIKE);
spells[3].targettype = TARGET_ATTACKING;
spells[3].instant = true;
spells[3].cooldown = 20;
spells[3].perctrigger = 8.0f;
spells[3].attackstoptimer = 1000;
spells[4].info = dbcSpell.LookupEntry(AGONIZING_FLAMES);
spells[4].targettype = TARGET_RANDOM_DESTINATION;
spells[4].instant = true;
spells[4].cooldown = 25;
spells[4].perctrigger = 7.0f;
spells[4].attackstoptimer = 1000;
spells[4].mindist2cast = 0.0f;
spells[4].maxdist2cast = 30.0f;
spells[4].minhp2cast = 0;
spells[4].maxhp2cast = 100;
spells[5].info = dbcSpell.LookupEntry(ENRAGE);
spells[5].targettype = TARGET_SELF;
spells[5].instant = true;
spells[5].cooldown = 0;
spells[5].perctrigger = 0.0f;
spells[5].attackstoptimer = 1000;
spells[5].speech = "You've wasted too much time mortals, now you shall fall!";
spells[5].soundid = 11474;
spells[6].info = dbcSpell.LookupEntry(SHADOW_BLAST);
spells[6].targettype = TARGET_DESTINATION;
spells[6].instant = false;
spells[6].cooldown = 0;
spells[6].perctrigger = 0.0f;
spells[6].attackstoptimer = 1000;
spells[7].info = dbcSpell.LookupEntry(SUMMON_DEMON);
spells[7].targettype = TARGET_SELF; // ?
spells[7].instant = false;
spells[7].cooldown = 0;
spells[7].perctrigger = 0.0f;
spells[7].attackstoptimer = 1000;
spells[8].info = dbcSpell.LookupEntry(SHADOW_PRISON);
spells[8].targettype = TARGET_VARIOUS;
spells[8].instant = true;
spells[8].cooldown = 0;
spells[8].perctrigger = 0.0f;
spells[8].attackstoptimer = 1000;
/* Spells after this point are not counted when using the SpellCast()
funct in AI and need to be manually triggered! :-D */
spells[9].info = dbcSpell.LookupEntry(DEMON_FORM1);
spells[9].instant = true;
spells[9].cooldown = 0;
spells[9].perctrigger = 0.0f;
spells[9].attackstoptimer = 1000;
spells[10].info = dbcSpell.LookupEntry(DEMON_FORM2);
spells[10].instant = true;
spells[10].cooldown = 0;
spells[10].perctrigger = 0.0f;
spells[11].info = dbcSpell.LookupEntry(DEMON_FORM3);
spells[11].instant = true;
spells[11].cooldown = 0;
spells[11].perctrigger = 0.0f;
spells[12].info = dbcSpell.LookupEntry(FIREBALL);
spells[12].targettype = TARGET_RANDOM_DESTINATION;
spells[12].instant = false;
spells[12].cooldown = 0;
spells[12].perctrigger = 0.0f;
spells[13].info = dbcSpell.LookupEntry(DARK_BARRAGE);
spells[13].targettype = TARGET_RANDOM_SINGLE;
spells[13].instant = false;
spells[13].cooldown = 0;
spells[13].perctrigger = 0.0f;
spells[13].cooldown = 44;
spells[14].info = dbcSpell.LookupEntry(EYE_BLAST1);
spells[14].instant = false;
spells[14].cooldown = 0;
spells[14].perctrigger = 0.0f;
/* Setup Illidan */
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9);
_unit->CastSpell(_unit, dbcSpell.LookupEntry(SKULL_INTRO), true);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
_unit->GetAIInterface()->m_canMove = false;
/* Initialize variables and stuff, I Guess */
FoA1 = FoA2 = Maiev = NULL;
DeathEvent[_unit->GetInstanceID()] = 0;
m_phase[_unit->GetInstanceID()] = 0; // must be 0 to use it with some other stuff.
DemonSoundRand = false;
DemonPhaseTimer = 0;
BladesEvent = 0;
MaievDialog = 0;
DemonPhase = 0;
}
void OnCombatStart(Unit* mTarget)
{
RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME));
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_READY1H);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);
_unit->GetAIInterface()->m_canMove = true;
DeathEvent[_unit->GetInstanceID()] = 0;
m_phase[_unit->GetInstanceID()] = 1;
DemonPhaseTimer = 0;
DemonPhase = 0;
for (int i = 0; i < nrspells; i++)
spells[i].casttime = 0;
spells[13].casttime = 0;
}
void OnTargetDied(Unit* mTarget)
{
if (_unit->GetHealthPct() > 0)
{
int RandomSpeach = rand()%2;
switch (RandomSpeach)
{
case 0:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Who shall be next to taste my blades?!");
_unit->PlaySoundToSet(11473);
break;
case 1:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "This is too easy!");
_unit->PlaySoundToSet(11472);
break;
}
}
}
void OnCombatStop(Unit *mTarget)
{
std::vector<Creature*> DespawnTable; /* From M4ksiu - Big THX to Capt who learned me how to use std stuff <3 */
/* If anyone wants to use this function, then leave this note! */
for(set<Object*>::iterator itr = _unit->GetInRangeSetBegin(); itr != _unit->GetInRangeSetEnd(); ++itr)
{
if ((*itr)->GetTypeId()== TYPEID_UNIT && (*itr)->GetInstanceID() == _unit->GetInstanceID() && (*itr) != _unit)
{
Creature *CreatureToAdd = NULL;
CreatureToAdd = (Creature*)(*itr);
if (CreatureToAdd && CreatureToAdd->GetSQL_id() == 0 && (CreatureToAdd->GetEntry() == CN_FLAME_OF_AZZINOTH ||
CreatureToAdd->GetEntry() == CN_BLADE_OF_AZZINOTH || (_unit->isAlive() && CreatureToAdd->GetEntry() == CN_MAIEV)))
{
DespawnTable.push_back(CreatureToAdd);
}
}
}
for (uint32 i = 0; i < DespawnTable.size(); i++)
{
Creature *CreatureToDespawn = DespawnTable[i];
if (CreatureToDespawn)
CreatureToDespawn->Despawn(0,0);
}
DespawnTable.clear();
_unit->GetAIInterface()->SetAllowedToEnterCombat(true);
_unit->GetAIInterface()->disable_melee = false;
_unit->GetAIInterface()->m_moveFly = false;
_unit->GetAIInterface()->m_canMove = true;
RemoveAIUpdateEvent();
_unit->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0);
_unit->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, 0);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);
if (_unit->FindAura(DEMON_FORM))
_unit->RemoveAura(DEMON_FORM);
_unit->SetFloatValue(OBJECT_FIELD_SCALE_X , 1.3f);
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->SetAIState(STATE_IDLE);
DemonSoundRand = false;
DemonPhaseTimer = 0;
BladesEvent = 0;
DemonPhase = 0;
if (m_phase[_unit->GetInstanceID()] == 2)
{
_unit->Emote(EMOTE_ONESHOT_LAND);
WorldPacket data(SMSG_MOVE_UNSET_HOVER, 13);
data << _unit->GetNewGUID();
data << uint32(0);
_unit->SendMessageToSet(&data, false);
float x = _unit->m_spawn->x;
float y = _unit->m_spawn->y;
float z = _unit->m_spawn->z;
float o = _unit->m_spawn->o;
_unit->GetAIInterface()->MoveTo(x, y, z, o);
}
if (_unit->isAlive())
m_phase[_unit->GetInstanceID()] = 1;
else
m_phase[_unit->GetInstanceID()] = 0;
FoA1 = FoA2 = NULL;
}
void OnDied(Unit * mKiller)
{
RemoveAIUpdateEvent();
if (MaievDialog >= 28 && Maiev != NULL && Maiev->isAlive()) // it's workaround (added pointer check, coz if he dies when Maiev is not on battlefield then it will crash server)
{
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9);
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
_unit->SetUInt32Value(UNIT_FIELD_HEALTH, 1);
if(_unit->GetCurrentSpell() != NULL)
_unit->GetCurrentSpell()->cancel();
Maiev->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9);
Maiev->GetAIInterface()->SetAIState(STATE_IDLE);
Maiev->WipeTargetList();
Maiev->WipeHateList();
DeathEvent[_unit->GetInstanceID()] = 1;
Maiev = NULL;
}
else
{
GameObject* RightGate = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(745.07f, 241.802f, 354.292f, 200000);
GameObject* LeftGate = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(744.829f, 369.276f, 354.324f, 200001);
if (RightGate != NULL)
RightGate->SetUInt32Value(GAMEOBJECT_STATE, 0);
if (LeftGate != NULL)
LeftGate->SetUInt32Value(GAMEOBJECT_STATE, 0);
}
}
void AIUpdate()
{
if (DemonPhase > 0 && DemonPhase < 75) // 0;9
{
DemonTrans();
}
else if (DemonPhase > 75 && DemonPhase < 134) // 9;17
{
TransRevert();
}
else
{
if (m_phase[_unit->GetInstanceID()] == 1) // First Phase (without demon form)
{
PhaseOne();
}
if (m_phase[_unit->GetInstanceID()] == 2) // Second Phase (Fly phase)
{
PhaseTwo();
}
if (m_phase[_unit->GetInstanceID()] == 3) // Third Phase normal form with ability to change into Demon
{
PhaseThree();
}
if (m_phase[_unit->GetInstanceID()] == 4) // Fourth Phase Demon Form
{
PhaseFour();
}
if (m_phase[_unit->GetInstanceID()] == 5) // Fifth Phase with ability to change into Demon and Enrage
{
PhaseFive();
}
}
}
void PhaseOne()
{
if (_unit->GetHealthPct() <= 65 && _unit->GetCurrentSpell() == NULL)
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "I will not be touched by a rebels such as you!"); // not sure
_unit->PlaySoundToSet(11479);
_unit->GetAIInterface()->MoveTo(_unit->GetPositionX(), _unit->GetPositionY(), _unit->GetPositionZ() + 10.0f, _unit->GetOrientation());
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9);
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
_unit->GetAIInterface()->disable_melee = true;
_unit->GetAIInterface()->m_moveFly = true;
_unit->Emote(EMOTE_ONESHOT_LIFTOFF);
WorldPacket data(SMSG_MOVE_SET_HOVER, 13);
data << _unit->GetNewGUID();
data << uint32(0);
_unit->SendMessageToSet(&data, false);
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(500);
m_phase[_unit->GetInstanceID()] = 2;
CastCount = 5 + RandomUInt(2);
TriggerSpawned = false;
FireWallTimer = 0;
LastFireWall = 0;
BladesEvent = 1;
}
else
{
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_READY1H); // in OnCombatStart or in Dialog part it doesn't work (in places I wanted to add it)
float val = (float)RandomFloat(100.0f);
SpellCast(val);
}
}
void FoASummon() // little hacky way to spawn them by pushing into world, but proper spell won't work now
{ // we can eventually add them as pointers and trigger some events from here (like Blade's channeling)
FoA1 = _unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_FLAME_OF_AZZINOTH, 672.039246f, 326.748322f, 354.206390f, 0.207343f, true, false, 0, 0);
FoA2 = _unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_FLAME_OF_AZZINOTH, 673.008667f, 283.813660f, 354.267548f, 6.203853f, true, false, 0, 0);
if (FoA1 != NULL)
{
Unit *Blade = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(UnitPos[0].x, UnitPos[0].y, UnitPos[0].z, CN_BLADE_OF_AZZINOTH);
if (Blade != NULL)
{
Blade->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, FoA1->GetGUID());
Blade->SetUInt32Value(UNIT_CHANNEL_SPELL, TEAR_OF_AZZINOTH_CHANNEL);
}
}
if (FoA2 != NULL)
{
Unit *Blade = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(UnitPos[1].x, UnitPos[1].y, UnitPos[1].z, CN_BLADE_OF_AZZINOTH);
if (Blade != NULL)
{
Blade->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, FoA2->GetGUID());
Blade->SetUInt32Value(UNIT_CHANNEL_SPELL, TEAR_OF_AZZINOTH_CHANNEL);
}
}
}
void PhaseTwo()
{
if ((BladesEvent && BladesEvent < 20) || (BladesEvent > 24 && BladesEvent < 45))
{
switch (BladesEvent)
{
case 2:
_unit->GetAIInterface()->StopMovement(0);
_unit->GetAIInterface()->SetAIState(STATE_SCRIPTMOVE);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_WANTEDWP);
_unit->GetAIInterface()->setWaypointToMove(1);
break;
case 10: // Blade1 fly
_unit->CastSpell(_unit, dbcSpell.LookupEntry(THROW_GLAIVE2), false);
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Behold the flames of Azzinoth!");
_unit->PlaySoundToSet(11480);
break;
case 12:
for (int i = 0; i < 2; i++)
{
_unit->CastSpellAoF(UnitPos[i].x, UnitPos[i].y, UnitPos[i].z, dbcSpell.LookupEntry(THROW_GLAIVE1), false);
}
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
break;
case 14: // Blades spawn
for (int i = 0; i < 2; i++)
{
Creature *Blade = _unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_BLADE_OF_AZZINOTH, UnitPos[i].x, UnitPos[i].y, UnitPos[i].z, UnitPos[i].o, false, false, 0, 0);
if (Blade != NULL)
{
Blade->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
Blade->GetAIInterface()->SetAllowedToEnterCombat(false);
Blade->m_noRespawn = true;
}
}
break;
case 18: // Flames of Azzinoth Spawn + channeling
FoASummon();
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(1000);
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
CastCount = 5 + RandomUInt(2);
TriggerSpawned = false;
FireWallTimer = 0;
break;
case 29:
for (int i = 0 ; i < 2; i++)
{
Creature *Blade = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(UnitPos[i].x, UnitPos[i].y, UnitPos[i].z, CN_BLADE_OF_AZZINOTH);
if (Blade != NULL)
{
Blade->Despawn(0,0);
}
}
break;
case 30: // Blades return
_unit->CastSpell(_unit, dbcSpell.LookupEntry(GLAIVE_RETURNS), false);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 1); // he should also make something like jump emote when weapons are in his hands, but I can't find right one o_O
break;
case 34:{
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_READY1H);
_unit->GetAIInterface()->m_moveFly = false;
_unit->Emote(EMOTE_ONESHOT_LAND);
WorldPacket data(SMSG_MOVE_UNSET_HOVER, 13);
data << _unit->GetNewGUID();
data << uint32(0);
_unit->SendMessageToSet(&data, false);
}break;
case 40: //36
_unit->GetAIInterface()->SetAllowedToEnterCombat(true);
_unit->GetAIInterface()->disable_melee = false;
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, 0);
_unit->GetAIInterface()->m_canMove = true;
_unit->GetAIInterface()->ClearHateList();
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME));
DemonPhaseTimer = (uint32)time(NULL) + 60;
m_phase[_unit->GetInstanceID()] = 3;
TriggerSpawned = false;
FireWallTimer = 0;
MaievDialog = 0;
break;
}
if (BladesEvent != 3)
BladesEvent++;
}
else
{
uint32 FoADeaths = 2;
if ((FoA1 != NULL && !FoA1->isAlive()) || FoA1 == NULL)
{
Unit *Blade = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(UnitPos[0].x, UnitPos[0].y, UnitPos[0].z, CN_BLADE_OF_AZZINOTH);
if (Blade != NULL)
{
Blade->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0);
Blade->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
}
FoADeaths--;
FoA1 = NULL;
}
if ((FoA2 != NULL && !FoA2->isAlive()) || FoA2 == NULL)
{
Unit *Blade = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(UnitPos[1].x, UnitPos[1].y, UnitPos[1].z, CN_BLADE_OF_AZZINOTH);
if (Blade != NULL)
{
Blade->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0);
Blade->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
}
FoADeaths--;
FoA2 = NULL;
}
FireWallTimer++;
if (_unit->GetAIInterface()->getMoveType() != MOVEMENTTYPE_WANTEDWP && _unit->GetCurrentSpell() == NULL)
{
if (_unit->GetUInt32Value(UNIT_CHANNEL_SPELL) == 0)
{
if (FoADeaths == 0)
{
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9);
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
_unit->GetAIInterface()->m_canMove = true;
if(_unit->GetCurrentSpell() != NULL)
_unit->GetCurrentSpell()->cancel();
_unit->GetAIInterface()->StopMovement(0);
_unit->GetAIInterface()->SetAIState(STATE_SCRIPTMOVE);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_WANTEDWP);
_unit->GetAIInterface()->setWaypointToMove(4);
return;
}
if (CastCount <= 0)
{
if (RandomUInt(2) == 1) // Move right
{
CurrentWP++;
if (CurrentWP > 3)
CurrentWP = 1;
}
else // Move left
{
CurrentWP--;
if (CurrentWP < 1)
CurrentWP = 3;
}
_unit->GetAIInterface()->StopMovement(0);
_unit->GetAIInterface()->SetAIState(STATE_SCRIPTMOVE);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_WANTEDWP);
_unit->GetAIInterface()->setWaypointToMove(CurrentWP);
return;
}
}
if (_unit->GetAIInterface()->getCurrentWaypoint() != 4)
{
if (FireWallTimer >= 30)
{
if (TriggerSpawned == false)
{
float posX;
float posY;
float posZ;
uint32 RandomWall = rand()%8+1;
while ((RandomWall == LastFireWall) || (RandomWall == LastFireWall - 4) || (RandomWall == LastFireWall + 4))
{
RandomWall = rand()%8+1;
}
switch (RandomWall)
{
case 1:
posX = 642.240601f;
posY = 297.297180f;
posZ = 353.423401f;
break;
case 2:
posX = 641.197449f;
posY = 314.330963f;
posZ = 353.300262f;
break;
case 3:
posX = 657.239807f;
posY = 256.925568f;
posZ = 352.996094f;
break;
case 4:
posX = 657.913330f;
posY = 353.562775f;
posZ = 352.996185f;
break;
case 5:
posX = 707.019043f;
posY = 270.441772f;
posZ = 352.996063f;
break;
case 6:
posX = 706.592407f;
posY = 343.425568f;
posZ = 352.996124f;
break;
case 7:
posX = 706.593262f;
posY = 310.011475f;
posZ = 353.693848f;
break;
case 8:
posX = 706.751343f;
posY = 298.312683f;
posZ = 353.653809f;
break;
}
Unit *Trigger = NULL;
Trigger = _unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_EYE_BEAM_TRIGGER, posX, posY, posZ, 0.0f, false, false, 0, 0);
if (Trigger != NULL)
{
if (_unit->GetCurrentSpell() != NULL)
_unit->GetCurrentSpell()->cancel();
_unit->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, Trigger->GetGUID());
_unit->SetUInt32Value(UNIT_CHANNEL_SPELL, EYE_BLAST1);
_unit->CastSpell(Trigger, spells[14].info, true);
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Stare into the eyes of the Betrayer!"); // must check this
_unit->PlaySoundToSet(11481);
LastFireWall = RandomWall;
TriggerSpawned = true;
FireWallTimer = 30;
}
else
{
FireWallTimer = 0;
LastFireWall = 0;
}
}
if (TriggerSpawned == true && FireWallTimer >= 42)
{
_unit->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0);
_unit->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
_unit->RemoveAura(EYE_BLAST1);
TriggerSpawned = false;
FireWallTimer = 0;
}
}
else if (_unit->GetAIInterface()->GetNextTarget())
{
Unit* target = NULL;
target = _unit->GetAIInterface()->GetNextTarget();
uint32 t = (uint32)time(NULL);
uint32 Spell = RandomUInt(100);
if (Spell >= 0 && Spell <= 25)
{
CastSpellOnRandomTarget(12, 0.0f, 60.0f, 0, 100);
CastCount--;
}
if (Spell > 25 && Spell <= 35 && t > spells[13].casttime)
{
CastSpellOnRandomTarget(13, 0.0f, 60.0f, 0, 100);
spells[13].casttime = t + spells[13].cooldown;
CastCount--;
}
}
}
}
}
}
void PhaseThree()
{
if (_unit->GetHealthPct() <= 30 && MaievDialog == 0 && (DemonPhase <= 0 || DemonPhase >= 135 && _unit->GetCurrentSpell() == NULL))
{
#ifdef USE_SHADOW_PRISON
_unit->GetAIInterface()->StopMovement(1);
_unit->CastSpell(_unit, spells[8].info, spells[8].instant);
#endif
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9);
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->disable_melee = true;
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
_unit->GetAIInterface()->m_canMove = false;
if(_unit->GetCurrentSpell() != NULL) // keeping it for now, will delete it later anyway
_unit->GetCurrentSpell()->cancel();
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(1000);
MaievDialog = 1;
}
if (MaievDialog > 0 && MaievDialog < 32 && (DemonPhase <= 0 || DemonPhase >= 135))
{
switch (MaievDialog)
{
case 3: // 3
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Is this it, mortals? Is this all the fury you can muster?");
_unit->PlaySoundToSet(11476);
break;
case 6: // 6
_unit->Emote(EMOTE_ONESHOT_QUESTION);
break;
case 9:
SpawnMaiev();
break;
case 10:
Maiev->CastSpell(_unit, dbcSpell.LookupEntry(TELEPORT), true);
_unit->GetAIInterface()->SetNextTarget(Maiev);
break;
case 11: // 12
Maiev->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Their fury pales before mine, Illidan. We have some unsettled business between us.");
Maiev->PlaySoundToSet(11491);
break;
case 12: // 13
MaievWeaponOff();
break;
case 13: // 14
Maiev->Emote(EMOTE_ONESHOT_EXCLAMATION);
break;
case 18: // 20
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Maiev... How is it even possible?");
_unit->PlaySoundToSet(11477);
break;
case 21: // 23
//_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_READY1H);
break;
case 24: // 27
Maiev->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Ah, my long hunt is finally over. Today, Justice will be done!");
Maiev->PlaySoundToSet(11492);
Maiev->Emote(EMOTE_ONESHOT_EXCLAMATION);
break;
case 27: // 30
Maiev->Emote(EMOTE_ONESHOT_YES);
break;
case 28: // 31
Maiev->Emote(EMOTE_ONESHOT_ROAR);
break;
case 31: //34
_unit->GetAIInterface()->SetAllowedToEnterCombat(true);
_unit->GetAIInterface()->disable_melee = false;
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, 0);
_unit->GetAIInterface()->m_canMove = true;
if (Maiev != NULL && Maiev->isAlive())
{
Maiev->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_READY1H);
Maiev->GetAIInterface()->SetAllowedToEnterCombat(true);
Maiev->GetAIInterface()->setCurrentAgent(AGENT_NULL);
Maiev->GetAIInterface()->SetAIState(STATE_IDLE);
Maiev->GetAIInterface()->m_canMove = true;
Maiev->GetAIInterface()->AttackReaction(_unit, 1, 0);
MaievWeaponOn();
}
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME));
DemonPhaseTimer = (uint32)time(NULL) + 60;
m_phase[_unit->GetInstanceID()] = 5;
EnrageTimer = 10;
break;
}
MaievDialog++;
}
else
{
uint32 t = (uint32)time(NULL);
if (t > DemonPhaseTimer)
{
_unit->GetAIInterface()->setCurrentAgent(AGENT_SPELL);
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
if(_unit->GetCurrentSpell() != NULL)
_unit->GetCurrentSpell()->cancel();
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(250);
DemonPhase = 1;
}
else
{
if (DemonPhase < 1 || DemonPhase > 134)
{
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_READY1H);
float val = (float)RandomFloat(100.0f);
SpellCast(val);
}
}
}
}
void DemonTrans() // check and change how long spell 9 is in use on official
{
if(_unit->GetCurrentSpell() != NULL)
_unit->GetCurrentSpell()->cancel();
switch (DemonPhase)
{ // let's give it 4 free triggers to not use melee attacks and spells
case 5:
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 403);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
break;
case 13:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Behold the power... of the demon within!");
_unit->PlaySoundToSet(11475);
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 404);
break;
case 33:
_unit->CastSpell(_unit, DEMON_FORM, true);
_unit->SetFloatValue(OBJECT_FIELD_SCALE_X , 5.0f);
break;
case 43:
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 405);
break;
case 53:{
_unit->GetAIInterface()->ClearHateList();
Unit *NewTarget = NULL;
NewTarget = FindTarget();
if (NewTarget != NULL)
_unit->GetAIInterface()->modThreatByPtr(NewTarget, 200);
}break;
case 61: //63 //65 // he should also drop aggro and take new target (warlock should take it by dots casted before final change)
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME));
PhaseFour();
DemonPhaseTimer = (uint32)time(NULL) + 30;
m_phase[_unit->GetInstanceID()] = 4;
DemonSoundRand = false;
DemonPhase = 74;
break;
}
DemonPhase++;
}
void TransRevert() // same here to spell 9 (but not that much I think); also I am thinking about changing spells on emotes
{
if(_unit->GetCurrentSpell() != NULL)
_unit->GetCurrentSpell()->cancel();
switch (DemonPhase)
{
case 81: // 1 diff is too long?
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 403);
break;
case 84: //85
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 404);
break;
case 108: //108 //109
if (_unit->FindAura(DEMON_FORM))
_unit->RemoveAura(DEMON_FORM);
_unit->SetFloatValue(OBJECT_FIELD_SCALE_X , 1.3f);
_unit->GetAIInterface()->ClearHateList();
break;
case 114: //116 //117
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 405);
break;
case 118:
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);
break;
case 126:
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
if (MaievDialog == 0)
m_phase[_unit->GetInstanceID()] = 3;
else
{
EnrageTimer = rand()%10+11;
m_phase[_unit->GetInstanceID()] = 5;
}
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME));
DemonPhaseTimer = (uint32)time(NULL) + 60;
DemonPhase = 135;
break;
}
DemonPhase++;
}
void PhaseFour()
{
uint32 t = (uint32)time(NULL);
if (t > DemonPhaseTimer || (_unit->GetHealthPct() <= 30 && MaievDialog == 0))
{
_unit->GetAIInterface()->setCurrentAgent(AGENT_SPELL);
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(250);
DemonSoundRand = false;
DemonPhase = 76;
}
if (t <= DemonPhaseTimer - 26 && MaievDialog > 0 && !DemonSoundRand)
{
int Sound = rand()%3; // 66% chance to say something, should work fine
switch (Sound)
{
case 0:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "You know nothing of power!");
_unit->PlaySoundToSet(11469);
DemonSoundRand = true;
break;
case 1:
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Such arrogance!");
_unit->PlaySoundToSet(11471);
DemonSoundRand = true;
break;
}
}
else
{
if (_unit->GetAIInterface()->GetNextTarget() != NULL && DemonPhase == 75 && _unit->GetCurrentSpell() == NULL)
{
Unit *target = NULL;
target = _unit->GetAIInterface()->GetNextTarget();
if (_unit->GetDistance2dSq(target) >= 0.0f && _unit->GetDistance2dSq(target) <= 4900.0f)
{
_unit->GetAIInterface()->setCurrentAgent(AGENT_SPELL);
_unit->GetAIInterface()->StopMovement(1);
int Spell = rand()%100;
if (Spell >= 0 && Spell <= 80)
_unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[6].info, spells[6].instant);
if (Spell > 80 && Spell <= 90) return;
//_unit->CastSpell(_unit, spells[7].info, spells[7].instant); // disabled for now as it can cause some unneeded animations // both should have _unit as target
if (Spell > 90 && Spell <= 100)
_unit->CastSpell(_unit, spells[1].info, spells[1].instant); // this one needs to be scripted
}
else
{
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
}
}
}
}
void PhaseFive()
{
EnrageTimer--;
uint32 t = (uint32)time(NULL);
if (t > DemonPhaseTimer)
{
_unit->GetAIInterface()->setCurrentAgent(AGENT_SPELL);
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
if(_unit->GetCurrentSpell() != NULL)
_unit->GetCurrentSpell()->cancel();
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(250);
DemonPhase = 1;
}
if (!EnrageTimer)
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "You've wasted too much time mortals, now you shall fall!");
_unit->PlaySoundToSet(11474);
_unit->CastSpell(_unit, spells[5].info, spells[5].instant);
return;
}
else
{
if (DemonPhase < 1 || DemonPhase > 134)
{
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_READY1H);
float val = (float)RandomFloat(100.0f);
SpellCast(val);
}
}
}
void SpellCast(float val)
{
if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
{
float comulativeperc = 0;
Unit *target = NULL;
for(int i=0;i<nrspells;i++)
{
if(!spells[i].perctrigger) continue;
if(m_spellcheck[i])
{
target = _unit->GetAIInterface()->GetNextTarget();
switch(spells[i].targettype)
{
case TARGET_SELF:
case TARGET_VARIOUS:
_unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
case TARGET_ATTACKING:
_unit->CastSpell(target, spells[i].info, spells[i].instant); break;
case TARGET_DESTINATION:
_unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
case TARGET_RANDOM_FRIEND:
case TARGET_RANDOM_SINGLE:
case TARGET_RANDOM_DESTINATION:
CastSpellOnRandomTarget(i, spells[i].mindist2cast, spells[i].maxdist2cast, spells[i].minhp2cast, spells[i].maxhp2cast); break;
}
m_spellcheck[i] = false;
return;
}
uint32 t = (uint32)time(NULL);
if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger) && t > spells[i].casttime)
{
if ((i == 4 && m_phase[_unit->GetInstanceID()] == 3) || i != 4)
{
_unit->setAttackTimer(spells[i].attackstoptimer, false);
spells[i].casttime = t + spells[i].cooldown;
m_spellcheck[i] = true;
}
}
comulativeperc += spells[i].perctrigger;
}
}
}
void CastSpellOnRandomTarget(uint32 i, float mindist2cast, float maxdist2cast, int minhp2cast, int maxhp2cast)
{
if (!maxdist2cast) maxdist2cast = 100.0f;
if (!maxhp2cast) maxhp2cast = 100;
if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
{
std::vector<Unit*> TargetTable; /* From M4ksiu - Big THX to Capt who helped me with std stuff to make it simple and fully working <3 */
/* If anyone wants to use this function, then leave this note! */
for(set<Object*>::iterator itr = _unit->GetInRangeSetBegin(); itr != _unit->GetInRangeSetEnd(); ++itr)
{
if (((spells[i].targettype == TARGET_RANDOM_FRIEND && isFriendly(_unit, (*itr))) || (spells[i].targettype != TARGET_RANDOM_FRIEND && isHostile(_unit, (*itr)) && (*itr) != _unit)) && ((*itr)->GetTypeId()== TYPEID_UNIT || (*itr)->GetTypeId() == TYPEID_PLAYER) && (*itr)->GetInstanceID() == _unit->GetInstanceID()) // isAttackable(_unit, (*itr)) &&
{
Unit* RandomTarget = NULL;
RandomTarget = (Unit*)(*itr);
if (RandomTarget->isAlive() && _unit->GetDistance2dSq(RandomTarget) >= mindist2cast*mindist2cast && _unit->GetDistance2dSq(RandomTarget) <= maxdist2cast*maxdist2cast && ((RandomTarget->GetHealthPct() >= minhp2cast && RandomTarget->GetHealthPct() <= maxhp2cast && spells[i].targettype == TARGET_RANDOM_FRIEND) || (_unit->GetAIInterface()->getThreatByPtr(RandomTarget) > 0 && isHostile(_unit, RandomTarget))))
{
TargetTable.push_back(RandomTarget);
}
}
}
if (_unit->GetHealthPct() >= minhp2cast && _unit->GetHealthPct() <= maxhp2cast && spells[i].targettype == TARGET_RANDOM_FRIEND)
TargetTable.push_back(_unit);
if (!TargetTable.size())
return;
size_t RandTarget = rand()%TargetTable.size();
Unit * RTarget = TargetTable[RandTarget];
if (!RTarget)
return;
switch (spells[i].targettype)
{
case TARGET_RANDOM_FRIEND:
case TARGET_RANDOM_SINGLE:
_unit->CastSpell(RTarget, spells[i].info, spells[i].instant); break;
case TARGET_RANDOM_DESTINATION:
_unit->CastSpellAoF(RTarget->GetPositionX(), RTarget->GetPositionY(), RTarget->GetPositionZ(), spells[i].info, spells[i].instant); break;
}
TargetTable.clear();
}
}
void SpawnMaiev() // this doesn't have collision checks! so keep in mind that Maiev can be spawned behind walls!
{
float xchange = (float)RandomFloat(15.0f);
float distance = 15.0f;
float ychange = sqrt(distance*distance - xchange*xchange);
if (rand()%2 == 1)
xchange *= -1;
if (rand()%2 == 1)
ychange *= -1;
float newposx = _unit->GetPositionX() + xchange;
float newposy = _unit->GetPositionY() + ychange;
Maiev = _unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_MAIEV, newposx, newposy, _unit->GetPositionZ() + 0.5f, 2.177125f, true, false, 0, 0);
if (Maiev == NULL)
{
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(20000);
MaievDialog = 30;
}
else
{
Maiev->GetAIInterface()->SetNextTarget(_unit);
}
}
void MaievWeaponOff()
{
/*Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01, 44850);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 0);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_01, 0);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_02, 218169346);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_03, 4);
Maiev->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);*/
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01, 44850);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 0);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_01, 0);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_02, 33488898);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_03, 781);
Maiev->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
}
void MaievWeaponOn()
{
/*Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 44850);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01, 0);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 218169346);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_01, 4);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_02, 0);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_03, 0);
Maiev->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);*/
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 44850);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01, 0);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 33488898);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_01, 781);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_02, 0);
Maiev->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO_03, 0);
Maiev->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);
}
void OnReachWP(uint32 iWaypointId, bool bForwards)
{
CurrentWP = iWaypointId;
switch(iWaypointId)
{
case 1:
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->SetAIState(STATE_SCRIPTIDLE);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
_unit->GetAIInterface()->setWaypointToMove(0);
if (BladesEvent < 4)
{
_unit->GetAIInterface()->ClearHateList();
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(500);
BladesEvent = 4;
}
CastCount = 5 + RandomUInt(2);
break;
case 2:
case 3:
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->SetAIState(STATE_SCRIPTIDLE);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
_unit->GetAIInterface()->setWaypointToMove(0);
CastCount = 5 + RandomUInt(2);
break;
case 4:
_unit->GetAIInterface()->m_canMove = false;
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->SetAIState(STATE_SCRIPTIDLE);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
_unit->GetAIInterface()->setWaypointToMove(0);
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(500);
BladesEvent = 25;
break;
}
}
Unit *FindTarget()
{
std::vector<Unit*> TargetTable; /* From M4ksiu - Big THX to Capt who helped me with std stuff to make it simple and fully working <3 */
/* If anyone wants to use this function, then leave this note! */
for(set<Object*>::iterator itr = _unit->GetInRangeSetBegin(); itr != _unit->GetInRangeSetEnd(); ++itr)
{
if (isHostile(_unit, (*itr)) && (*itr)->GetTypeId() == TYPEID_PLAYER && (*itr)->GetInstanceID() == _unit->GetInstanceID())
{
Unit* RandomTarget = NULL;
RandomTarget = (Unit*)(*itr);
if (RandomTarget->isAlive() && _unit->GetDistance2dSq(RandomTarget) <= 10000.0f && _unit->GetDistance2dSq(RandomTarget) >= 0.0f && _unit->GetAIInterface()->getThreatByPtr(RandomTarget) > 0)
{
TargetTable.push_back(RandomTarget);
}
}
}
if (!TargetTable.size())
return NULL;
size_t RandTarget = rand()%TargetTable.size();
Unit * RTarget = TargetTable[RandTarget];
if (!RTarget)
return NULL;
TargetTable.clear();
return RTarget;
}
inline WayPoint* CreateWaypoint(int id, uint32 waittime, uint32 flags)
{
WayPoint * wp = _unit->CreateWaypointStruct();
wp->id = id;
wp->x = ForIllidan[id].x;
wp->y = ForIllidan[id].y;
wp->z = ForIllidan[id].z;
wp->o = ForIllidan[id].o;
wp->waittime = waittime;
wp->flags = flags;
wp->forwardemoteoneshot = 0;
wp->forwardemoteid = 0;
wp->backwardemoteoneshot = 0;
wp->backwardemoteid = 0;
wp->forwardskinid = 0;
wp->backwardskinid = 0;
return wp;
}
protected:
uint32 DemonPhaseTimer;
uint32 FireWallTimer;
bool DemonSoundRand;
uint32 LastFireWall;
bool TriggerSpawned;
uint32 BladesEvent;
uint32 MaievDialog;
uint32 CurrentWP;
int EnrageTimer;
int DemonPhase;
int CastCount;
int nrspells;
Unit* Maiev;
Unit* FoA1;
Unit* FoA2;
};