[ASCENT] illidan problem and object problem
i have 2 problems
1. in BT, i can't attack illidan, my mouse just goes over him. he also shows up as a 73 elite. also, akama (idk about spelling) only will say "hey there [character name], how can i help you?" he won' go up and help
2. after i completely shut down the servers, all the objects that i placed are gone!
please help me!
Re: [ASCENT] illidan problem and object problem
i don't know the answer to your first question, but i can help you out with the 2nd one (at least i hope so :icecream:)
when you are spawning a game_object use another paramater at the end of the syntax - "1"
".go spawn <OBJECT_ID> 1"this will tell ascent to permanently store your object in the database
Re: [ASCENT] illidan problem and object problem
Sometimes .gobject spawn <ID> 1 does not save objects... I've noticed this has happened on my server as well. If the parameter 1 does not save your gameobject, it's best to wait for a fix.
Re: [ASCENT] illidan problem and object problem
You need an illidan script to make akama run up to the door, open it, then run up and fight with illidan. If you dont want the illidan script, then try deleting illidan and respawning him, usually fixes it.
Re: [ASCENT] illidan problem and object problem
To open the door before illidan yourself, just stand in front of the door and use .gobject activate (might have to use .goject select first, but I'm not sure about that)
To activate illidan you should try to change his flags, .mod flags [number]
Re: [ASCENT] illidan problem and object problem
Can you give me a link where can I download different scripts for bosses?So they will work better.I am not good at search)
Re: [ASCENT] illidan problem and object problem
Not many people know how to make the scripts now that they are no longer .gm format. You need to find an LUA or .DLL script for things now.
Re: [ASCENT] illidan problem and object problem
the moon++ project has some working c++ instancescripts. also these done by M4ksiu.
download their svn repository and compile their instancescript solution.
http://217.149.194.150/svn/moonplusplus
some of the repack builder should use them, for those, not able to compile ascent.
Edit:
username : anonymous
password : *leave field empty/blank*
their homepage: www.moonplusplus.info :: Index
t4k
Re: [ASCENT] illidan problem and object problem
I need a pass and username..what do i enter there?
Re: [ASCENT] illidan problem and object problem
Ok..mm i found the script at that webpage but i dont know how to use it..can you pls add it to a new rev of ascent so we could be able to use it?....
Script:
#include "StdAfx.h"
#include "Setup.h"
// --- Instance_BlackTemple.cpp Script --- //
// --- Script made by M4ksiu --- //
// --- Illidan Encounter Event --- //
/* Global Variables */
// Additional stuff
uint32 m_phase;
uint32 WayStart;
uint32 FoADeaths;
uint32 MaievDialog;
// Events
uint32 DoorEvent; // we can take it as private var, but I will keep it for now (to keep everything in one place - cleaner)
uint32 BladesEvent;
uint32 DeathEvent;
// NPCs/Mobs/Creatures Pointers
Unit* Illidan;
Unit* Akama;
Unit* Maiev;
// Illidan's position
float IposX;
float IposY;
float IposZ;
// Akama's position
float AposX;
float AposY;
float AposZ;
// Maiev's position
float MposX;
float MposY;
float MposZ;
float MposO;
#define WALK 0
#define RUN 256
#define FLY 768
// Global definitions - comment to disable
#define USE_SHADOW_PRISON // aggroes a lot of mobs/NPCs if they are not friendly to Illidan
/* Flame of Azzinoth AI - Creature AI Class */
#define CN_FLAME_OF_AZZINOTH 22997
#define FA_MORTAL_STRIKE 37335
#define FA_TAUNT 37486
class FlameOfAzzinothAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(FlameOfAzzinothAI);
SP_AI_Spell spells[2];
bool m_spellcheck[2];
FlameOfAzzinothAI(Creature* pCreature) : CreatureAIScript(pCreature)
{
nrspells = 2;
for(int i=0;i<nrspells;i++)
{
m_spellcheck[i] = false;
}
spells[0].info = dbcSpell.LookupEntry(FA_MORTAL_STRIKE);
spells[0].targettype = TARGET_ATTACKING;
spells[0].instant = true;
spells[0].cooldown = -1;
spells[0].perctrigger = 8.0f;
spells[0].attackstoptimer = 1000;
spells[1].info = dbcSpell.LookupEntry(FA_TAUNT);
spells[1].targettype = TARGET_ATTACKING;
spells[1].instant = true;
spells[1].cooldown = -1;
spells[1].perctrigger = 7.0f;
spells[1].attackstoptimer = 1000;
}
void OnCombatStart(Unit* mTarget)
{
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();
FoADeaths--;
}
void AIUpdate()
{
float val = (float)sRand.rand(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++)
{
spells[i].casttime--;
if (m_spellcheck[i])
{
spells[i].casttime = spells[i].cooldown;
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;
}
if (spells[i].speech != "")
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, spells[i].speech.c_str());
_unit->PlaySoundToSet(spells[i].soundid);
}
m_spellcheck[i] = false;
return;
}
if ((val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger)) || !spells[i].casttime)
{
_unit->setAttackTimer(spells[i].attackstoptimer, false);
m_spellcheck[i] = true;
}
comulativeperc += spells[i].perctrigger;
}
}
}
protected:
int nrspells;
};
/* 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;
objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 1, plr);
Menu->AddItem( 0, "Let's free Outland!", 1);
if(AutoSend)
Menu->SendTo(plr);
}
void GossipSelectOption(Object* pObject, Player* plr, uint32 Id, uint32 IntId, const char * EnteredCode)
{
switch (IntId)
{
case 0:
GossipHello(pObject, plr, true);
break;
case 1:
{
pObject->SetUInt32Value(UNIT_NPC_FLAGS,0);
WayStart = 0;
}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 /* I couldn't find even animation for those o_O */
#define AKAMA_DOOR_FAIL 41271
#define AKAMA_DOOR_OPEN 41268
#define DEATHSWORN_DOOR_OPEN 41269
struct Coords
{
float x;
float y;
float z;
float o;
};
static Coords ToIllidan[] =
{
{ },
{ 661.563171f, 305.711304f, 271.689148f, 6.273761f },
{ 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 },
{ MposX, MposY, MposZ, MposO } // Illidan death event waypoint <-- a bit hack way, but I don't have time for that
};
class AkamaAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(AkamaAI);
SP_AI_Spell spells[3];
bool m_spellcheck[3];
AkamaAI(Creature* pCreature) : CreatureAIScript(pCreature)
{
for (int i = 1; i < 21; i++)
{
if (i == 17)
_unit->GetAIInterface()->addWayPoint(CreateWaypoint(i, 5000, RUN));
if (i == 18)
_unit->GetAIInterface()->addWayPoint(CreateWaypoint(i, 0, WALK));
else
_unit->GetAIInterface()->addWayPoint(CreateWaypoint(i, 0, RUN));
}
nrspells = 1;
for(int i=0;i<nrspells;i++)
{
m_spellcheck[i] = false;
}
spells[0].info = dbcSpell.LookupEntry(BLESSING_OF_KINGS);
spells[0].targettype = TARGET_SELF;
spells[0].instant = true;
spells[0].cooldown = -1;
spells[0].perctrigger = 7.5f;
spells[0].attackstoptimer = 1000;
spells[1].info = dbcSpell.LookupEntry(HEALING_POTION);
spells[1].targettype = TARGET_SELF;
spells[1].instant = true;
spells[1].cooldown = -1;
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 = -1;
spells[2].perctrigger = 0.0f;
spells[2].attackstoptimer = 1000;
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_SELECT);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->SetAIState(STATE_IDLE);
_unit->GetAIInterface()->m_moveRun = true;
RegisterAIUpdateEvent(1000);
if (!DeathEvent)
_unit->SetUInt32Value(UNIT_NPC_FLAGS, 1);
else _unit->SetUInt32Value(UNIT_NPC_FLAGS, 0);
MaievDialog = 0;
AkamaDialog = 0;
AkamaRun = 0;
WayStart = 2;
m_phase = 0;
}
void OnCombatStart(Unit* mTarget)
{
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);
SoundLimiter = 0;
//RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME));
}
void OnCombatStop(Unit *mTarget)
{
if (m_phase > 0)
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
//_unit->GetAIInterface()->SetAIState(STATE_IDLE);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
//RemoveAIUpdateEvent();
AkamaDialog = 0;
//AkamaRun = 0;
WayStart = 2;
//_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
}
void OnTargetDied(Unit* mTarget)
{
if (_unit->GetHealthPct() > 0)
{
int RandomSpeach;
sRand.randInt(1000);
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();
AkamaDialog = 0;
AkamaRun = 0;
WayStart = 2;
}
void OnSpawn()
{
if (DeathEvent)
{
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_SELECT);
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);
_unit->SetUInt32Value(UNIT_NPC_FLAGS, 0);
}
RegisterAIUpdateEvent(1000);
AkamaDialog = 0;
AkamaRun = 0;
WayStart = 2;
}
void OnDespawn()
{
RemoveAIUpdateEvent();
AkamaDialog = 0;
AkamaRun = 0;
WayStart = 2;
}
void AIUpdate()
{
SoundLimiter++;
if (_unit->GetHealthPct() <= 15)
{
int RandomSpeach = rand()%2;
if (SoundLimiter >= 15)
{
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 (m_phase == 1)
_unit->CastSpell(_unit, spells[1].info, spells[1].instant);
}
if (!m_phase && !WayStart && MaievDialog < 30)
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Stay close to me, my friends." );
_unit->GetAIInterface()->StopMovement(0);
_unit->GetAIInterface()->SetAIState(STATE_SCRIPTMOVE);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_WANTEDWP);
_unit->GetAIInterface()->setWaypointToMove(1);
DoorEvent = 0;
WayStart = 2;
}
if (WayStart == 1)
{/* We can't make it in blizzlike way so we will keep it just coded in the way we need it to get to Illidan */
GameObject* Gate = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(774.7f, 304.6f, 314.85f, 185905);
if (!Gate)
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "It's strange that Illidan doesn't protect himself against intruders." );
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_WANTEDWP);
_unit->GetAIInterface()->setWaypointToMove(8);
_unit->SetFacing(6.248631f);
WayStart = 2;
return;
}
switch (DoorEvent)
{
case 1:
{
_unit->SetFacing(6.248631f);
}break;
case 5:
{
_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 8: // here will be first try to break door (Akama himself only)
{
_unit->CastSpellAoF(750.949463f, 278.589417f, 356.99651f, dbcSpell.LookupEntry(AKAMA_DOOR_FAIL), false);
}break;
case 17: // here we will stop casting spell on door
{
//_unit->RemoveAura();
}break;
case 18:
{
_unit->Emote(EMOTE_ONESHOT_NO);
_unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "I cannot do this alone..." );
}break;
case 24: // 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)
{
Udalo->GetAIInterface()->SetAllowedToEnterCombat(false);
Udalo->SetUInt64Value(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_SELECT);
}
if (Olum)
{
Olum->GetAIInterface()->SetAllowedToEnterCombat(false);
Olum->SetUInt64Value(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_SELECT);
}
}break;
case 25:
{
if (Udalo)
Udalo->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "You are not alone, Akama." );
}break;
case 31:
{
if (Olum)
Olum->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Your people will always be with you." );
}break;
case 36: // Akama starts casting his spell again with both spirits
{
_unit->CastSpellAoF(750.949463f, 278.589417f, 356.99651f, dbcSpell.LookupEntry(AKAMA_DOOR_OPEN), false);
}break;
case 37:
{
if (Udalo)
Udalo->CastSpellAoF(750.949463f, 278.589417f, 356.99651f, dbcSpell.LookupEntry(DEATHSWORN_DOOR_OPEN), false);
if (Olum)
Olum->CastSpellAoF(750.949463f, 278.589417f, 356.99651f, dbcSpell.LookupEntry(DEATHSWORN_DOOR_OPEN), false);
}break;
case 46: // Door has been broken and channel stoped
{
Gate->SetUInt32Value(GAMEOBJECT_STATE, 0);
//_unit->RemoveAura();
}break;
case 50:
{
_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 53:
{
if (Udalo)
Udalo->Emote(EMOTE_ONESHOT_SALUTE);
if (Olum)
Olum->Emote(EMOTE_ONESHOT_SALUTE);
}break;
case 56:
{
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_WANTEDWP);
_unit->GetAIInterface()->setWaypointToMove(8);
WayStart = 2;
}break;
}
DoorEvent++;
}
if (AkamaDialog)
{
Illidan = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(704.539001f, 305.282013f, 353.919006f, 22917);
if (!Illidan || !Illidan->isAlive() && m_phase == 0 || !DeathEvent && !Illidan->isAlive()) // added check of Illidan's life state, coz some stupid GMs can kill Illidan by command before real part of event starts
{
_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);
AkamaDialog = 0;
return;
}
switch(AkamaDialog)
{
case 1:
{
_unit->GetAIInterface()->SetNextTarget(Illidan);
_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:
{
_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;
Illidan->GetAIInterface()->SetAllowedToEnterCombat(true);
Illidan->SetUInt64Value(UNIT_FIELD_FLAGS, 0);
Illidan->GetAIInterface()->m_canMove = true;
_unit->GetAIInterface()->AttackReaction(Illidan, 1, 0);
CastTriggering = 2;
AkamaRun = 0;
}break;
}
AkamaDialog++;
if (AkamaDialog == 45)
AkamaDialog = 0;
}
if (m_phase == 0 && DeathEvent >= 46)
{
if (_unit->GetPositionX() == MposX && _unit->GetPositionY() == MposY && _unit->GetPositionZ() == MposZ && DeathEvent < 49)
DeathEvent = 49;
if (DeathEvent == 48)
{
_unit->GetAIInterface()->MoveTo(MposX, MposY, MposZ, MposO);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);
_unit->GetAIInterface()->m_moveRun = true;
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(1000);
//_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_READY1H); // dunno why this emote sometimes bugs facing
//_unit->GetAIInterface()->SetNextTarget(Illidan);
}
if (DeathEvent >= 50)
{
switch (DeathEvent)
{
case 50:
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "The Light will fill these dismal halls once again. I swear it.");
_unit->PlaySoundToSet(11387);
if (Illidan)
_unit->GetAIInterface()->SetNextTarget(Illidan);
_unit->Emote(EMOTE_ONESHOT_TALK);
}break;
case 54:
{
_unit->Emote(EMOTE_ONESHOT_SALUTE);
}break;
case 58:
{
DeathEvent = 0;
_unit->CastSpell(_unit, spells[2].info, spells[2].instant);
_unit->Despawn(0,0);
}break;
}
}
if (DeathEvent >= 49)
DeathEvent++;
}
if (m_phase)
{
CastTriggering--;
if (!CastTriggering && AkamaRun < 7 && Illidan && Illidan->GetHealthPct() > 85)
{
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_READY1H);
float val = (float)sRand.rand(100.0f);
SpellCast(val);
CastTriggering = 2;
}
/*
if (Illidan->GetAIInterface()->getAITargetsCount() == 1 && AkamaRun == 7 && Illidan->GetAIInterface()->GetNextTarget() == _unit)
return;
if (m_phase > 1 && AkamaRun < 7) // those cases are needed, as if we won't disallow Akama
_unit->GetAIInterface()->m_canMove = false; // to move when ex. Illidan starts flying Akama will come
if (m_phase > 1 && AkamaRun >= 7) // with Illidan and will stay on main platform ----------
_unit->GetAIInterface()->m_canMove = true; // (battlefield) ----------------------------------------
*/
if ((!Illidan || !Illidan->isAlive()) && AkamaRun <= 7 || !DeathEvent && !Illidan->isAlive()) // added check for Illidan life state, coz some stupid GMs can kill Illidan by command before real part of event starts
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Not this time my friends." );
_unit->CastSpell(_unit, spells[2].info, spells[2].instant);
AkamaRun = 0;
_unit->Despawn(0,0);
return;
}
if (Illidan && Illidan->isAlive() && Illidan->GetHealthPct() <= 85 && AkamaRun <= 7 || AkamaRun > 7) // we don't need to check Illidan if AkamaRun > 7 coz we don't use him in that time (only _unit)
{
switch (AkamaRun)
{
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, U_FIELD_FLAG_UNIT_UNTACKABLE_SELECT);
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
_unit->GetAIInterface()->SetAIState(STATE_IDLE);
/*_unit->GetAIInterface()->WipeTargetList(); // it's strange that if Akama goes out of combat he affects Illidan so he won't cast or update ai correctly
_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
//_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
}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:
{
if (_unit->GetAIInterface()->getMoveType() != MOVEMENTTYPE_WANTEDWP)
{
// maybe something to stop Illidan from fight Akama, or switch target to PC something!
_unit->GetAIInterface()->m_canMove = true;
_unit->GetAIInterface()->StopMovement(0);
_unit->GetAIInterface()->SetAIState(STATE_SCRIPTMOVE);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_WANTEDWP);
_unit->GetAIInterface()->setWaypointToMove(19);
//_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
}
}break;
}
AkamaRun++;
}
}
}
void SpellCast(float val)
{
if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
{
float comulativeperc = 0;
Unit *target = NULL;
for(int i=0;i<nrspells;i++)
{
spells[i].casttime--;
if (m_spellcheck[i])
{
spells[i].casttime = spells[i].cooldown;
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;
}
if (spells[i].speech != "")
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, spells[i].speech.c_str());
_unit->PlaySoundToSet(spells[i].soundid);
}
m_spellcheck[i] = false;
return;
}
if ((val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger)) || !spells[i].casttime)
{
_unit->setAttackTimer(spells[i].attackstoptimer, false);
m_spellcheck[i] = true;
}
comulativeperc += spells[i].perctrigger;
}
}
}
void OnReachWP(uint32 iWaypointId, bool bForwards)
{
switch (iWaypointId)
{
case 7:
{
WayStart = 1;
}break;
case 17:
{
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_WANTEDWP);
_unit->GetAIInterface()->setWaypointToMove(18);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
_unit->SetFacing(1.509539f);
}break;
case 18:
{
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
_unit->GetAIInterface()->setWaypointToMove(0);
AkamaDialog = 1;
}break;
case 20:
{
//_unit->Despawn(0, 0); // do not let Illidan's AI being updated
}break;
case 21:
{
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
_unit->GetAIInterface()->setWaypointToMove(0);
DeathEvent = 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;
}
protected:
uint32 CastTriggering;
uint32 SoundLimiter;
uint32 m_currentWP;
uint32 AkamaDialog;
uint32 AkamaRun;
int nrspells;
Unit* Udalo;
Unit* Olum;
};
/* Blade of Azzinoth AI - Creature AI Class */
#define CN_BLADE_OF_AZZINOTH 22996
class BladeOfAzzinothAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(BladeOfAzzinothAI);
BladeOfAzzinothAI(Creature* pCreature) : CreatureAIScript(pCreature)
{
/*
spells[0].info = dbcSpell.LookupEntry();
spells[0].targettype = TARGET_;
spells[0].instant = true;
spells[0].cooldown = -1;
spells[0].perctrigger = 0.0f;
spells[0].attackstoptimer = 1000;
*/
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_NO_SELECT);
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
RegisterAIUpdateEvent(500);
//RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME));
}
void OnCombatStart(Unit* mTarget)
{
//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 OnSpawn()
{
RegisterAIUpdateEvent(500);
}
void OnDespawn()
{
RemoveAIUpdateEvent();
}
void AIUpdate()
{
switch (BladesEvent)
{
case 18: // Channeling (Flames of Azzinoth summoning)
{
//_unit->CastSpell(_unit, dbcSpell.LookupEntry(SUMMON_TEAR_OF_AZZINOTH), true);
}break;
case 29: // Despawn of Blades -> Return to Illidan's hands
{
_unit->Despawn(0,0);
}break;
}
}
protected:
int nrspells;
};
/* Flame Crash AI - Creature AI Class */
#define CN_FLAME_CRASH 23336
#define FLAME_CRASH_EFFECT 40836
#define INVISIBILITY 32754
class FlameCrashAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(FlameCrashAI);
FlameCrashAI(Creature* pCreature) : CreatureAIScript(pCreature)
{
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_NO_SELECT);
_unit->CastSpell(_unit, dbcSpell.LookupEntry(FLAME_CRASH_EFFECT), true);
_unit->GetAIInterface()->disable_melee = true;
_unit->GetAIInterface()->m_canMove = false;
RegisterAIUpdateEvent(1000);
DespawnTimer = 30;
//_unit->CastSpell(_unit, dbcSpell.LookupEntry(INVISIBILITY), true);
//_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
}
void OnCombatStart(Unit* mTarget)
{
RegisterAIUpdateEvent(1000);
}
void OnCombatStop(Unit *mTarget)
{
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->SetAIState(STATE_IDLE);
RemoveAIUpdateEvent();
}
void OnDied(Unit * mKiller)
{
RemoveAIUpdateEvent();
}
void OnSpawn()
{
RegisterAIUpdateEvent(1000);
DespawnTimer = 30;
}
void OnDespawn()
{
RemoveAIUpdateEvent();
}
void AIUpdate()
{
DespawnTimer--;
if (!DespawnTimer)
_unit->Despawn(0,0);
}
protected:
uint32 DespawnTimer;
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];
bool m_spellcheck[1];
MaievAI(Creature* pCreature) : CreatureAIScript(pCreature)
{
nrspells = 1;
for(int i=0;i<nrspells;i++)
{
m_spellcheck[i] = false;
}
spells[0].info = dbcSpell.LookupEntry(TELEPORT);
spells[0].targettype = TARGET_SELF;
spells[0].instant = true;
spells[0].cooldown = -1;
spells[0].perctrigger = 0.0f;
spells[0].attackstoptimer = 0;
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_SELECT);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
RegisterAIUpdateEvent(250);
CastTriggering = 0;
SoundTimer = 50;
//_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);
}
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 = 50;
}
void OnSpawn()
{
_unit->CastSpell(_unit, spells[0].info, spells[0].instant);
RegisterAIUpdateEvent(250); // I need to remember to add castTrigger to trigger spells correctly
SoundTimer = 50;
//_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);
}
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));
float val = (float)sRand.rand(100.0f);
SpellCast(val);
if (MaievDialog >= 29 && !DeathEvent)
SoundTimer++;
float SayNaisha = (float)sRand.rand(100.0f);
if ((SayNaisha < 2.5f && SoundTimer >= 100 && SoundTimer < 1330) || SoundTimer == 1361 || SoundTimer > 1400)
{
if (SoundTimer != 1361)
RandText = rand()%3;
//RandText = sRand.rand(3);
if (SoundTimer == 1361)
RandText = rand()%2;
//RandText = sRand.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)
{
Illidan->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Feel the hatred of ten thousand years!");
Illidan->PlaySoundToSet(11470);
SoundTimer = 1337;
}break;
}
}
if (DeathEvent && Illidan)
{
switch (DeathEvent)
{
case 1:
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Ah, it is finished. You are beaten."); // not sure
_unit->PlaySoundToSet(11496);
_unit->GetAIInterface()->SetAIState(STATE_IDLE);
_unit->WipeTargetList();
_unit->WipeHateList();
Illidan->SetUInt64Value(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_SELECT);
Illidan->GetAIInterface()->SetAllowedToEnterCombat(false);
Illidan->GetAIInterface()->setCurrentAgent(AGENT_NULL);
Illidan->GetAIInterface()->SetAIState(STATE_IDLE);
Illidan->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
Illidan->GetAIInterface()->SetNextTarget(NULL);
Illidan->Emote(EMOTE_ONESHOT_CUSTOMSPELL06);
Illidan->GetAIInterface()->StopMovement(0);
if(Illidan->GetCurrentSpell() != NULL)
Illidan->GetCurrentSpell()->cancel();
Illidan->WipeTargetList();
Illidan->WipeHateList();
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, "Maiev... How is it even possible?");
Illidan->PlaySoundToSet(11477);
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
//MaievWeaponOff();
}break;
case 11:
{
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);
}break;
case 31:
{
Illidan->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
Illidan->SetUInt32Value(UNIT_FIELD_HEALTH,0);
Illidan->setDeathState(JUST_DIED);
}break;
case 36:
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "He's right. I feel nothing. I am nothing.");
_unit->PlaySoundToSet(11497);
}break;
case 45:
{
//_unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_AKAMA, 739.545410f, 323.023743f, 352.996094f, 4.578086f, 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);
MposX = _unit->GetPositionX();
MposY = _unit->GetPositionY();
MposZ = _unit->GetPositionZ();
MposO = _unit->GetOrientation();
}break;
case 46:
{
_unit->CastSpell(_unit, dbcSpell.LookupEntry(TELEPORT), true);
}break;
case 47:
{
RemoveAIUpdateEvent();
_unit->Despawn(0,0);
}break;
}
if (DeathEvent <= 47)
DeathEvent++;
}
}
void SpellCast(float val)
{
if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
{
float comulativeperc = 0;
Unit *target = NULL;
for(int i=0;i<nrspells;i++)
{
spells[i].casttime--;
if (m_spellcheck[i])
{
spells[i].casttime = spells[i].cooldown;
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;
}
if (spells[i].speech != "")
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, spells[i].speech.c_str());
_unit->PlaySoundToSet(spells[i].soundid);
}
m_spellcheck[i] = false;
return;
}
if ((val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger)) || !spells[i].casttime)
{
_unit->setAttackTimer(spells[i].attackstoptimer, false);
m_spellcheck[i] = true;
}
comulativeperc += spells[i].perctrigger;
}
}
}
protected:
uint32 CastTriggering;
uint32 SoundTimer;
uint32 RandText;
int nrspells;
};
/* 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 AURA_OF_DREAD 41142
#define FIREBALL 40598 // +
#define DARK_BARRAGE 40585 // ? Haven't Tried
#define SUMMON_TEAR_OF_AZZINOTH 39855 // +
// 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
static Coords ForIllidan[] =
{
{ },
{ 709.783203f, 305.073883f, 362.988770f, 1.546307f },
{ 680.798157f, 305.648743f, 353.192200f, 3.196716f }
};
class IllidanStormrageAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(IllidanStormrageAI);
SP_AI_Spell spells[13];
bool m_spellcheck[13];
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, RUN));
nrspells = 8;
for(int i=0;i<nrspells;i++)
{
m_spellcheck[i] = false;
}
spells[0].info = dbcSpell.LookupEntry(SHEAR);
spells[0].targettype = TARGET_ATTACKING;
spells[0].instant = false;
spells[0].cooldown = -1;
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 = -1;
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 = -1;
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 = -1;
spells[3].perctrigger = 8.0f;
spells[3].attackstoptimer = 1000;
spells[4].info = dbcSpell.LookupEntry(ENRAGE);
spells[4].targettype = TARGET_SELF;
spells[4].instant = true;
spells[4].cooldown = -1;
spells[4].perctrigger = 0.0f;
spells[4].attackstoptimer = 1000;
spells[4].speech = "You've wasted too much time mortals, now you shall fall!";
spells[4].soundid = 11474;
spells[5].info = dbcSpell.LookupEntry(SHADOW_BLAST);
spells[5].targettype = TARGET_DESTINATION;
spells[5].instant = false;
spells[5].cooldown = -1;
spells[5].perctrigger = 0.0f;
spells[5].attackstoptimer = 1000;
spells[6].info = dbcSpell.LookupEntry(SUMMON_DEMON);
spells[6].targettype = TARGET_SELF; // ?
spells[6].instant = false;
spells[6].cooldown = -1;
spells[6].perctrigger = 0.0f;
spells[6].attackstoptimer = 1000;
spells[7].info = dbcSpell.LookupEntry(SHADOW_PRISON);
spells[7].targettype = TARGET_VARIOUS;
spells[7].instant = true;
spells[7].cooldown = -1;
spells[7].perctrigger = 0.0f;
spells[7].attackstoptimer = 1000;
/* Spells after this point are not counted when using the SpellCast()
funct in AI and need to be manually triggered! :-D */
spells[8].info = dbcSpell.LookupEntry(DEMON_FORM1);
spells[8].instant = true;
spells[8].cooldown = -1;
spells[8].perctrigger = 0.0f;
spells[8].attackstoptimer = 1000;
spells[9].info = dbcSpell.LookupEntry(DEMON_FORM2);
spells[9].instant = true;
spells[9].cooldown = -1;
spells[9].perctrigger = 0.0f;
spells[10].info = dbcSpell.LookupEntry(DEMON_FORM3);
spells[10].instant = true;
spells[10].cooldown = -1;
spells[10].perctrigger = 0.0f;
spells[11].info = dbcSpell.LookupEntry(FIREBALL);
spells[11].instant = false;
spells[11].cooldown = -1;
spells[11].perctrigger = 0.0f;
spells[12].info = dbcSpell.LookupEntry(DARK_BARRAGE);
spells[12].instant = false;
spells[12].cooldown = -1;
spells[12].perctrigger = 0.0f;
/* Setup Illidan */
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_SELECT);
_unit->CastSpell(_unit, dbcSpell.LookupEntry(SKULL_INTRO), true);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
_unit->GetAIInterface()->m_canMove = false;
/* Initialize variables and stuff, I Guess */
DemonSoundRand = false;
DemonPhaseTimer = 5;
BladesEvent = 0;
DemonPhase = 0;
DeathEvent = 0;
m_phase = 0; // must be 0 to use it with some other stuff.
}
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;
DemonPhaseTimer = 5;
DemonPhase = 0;
m_phase = 1;
}
void OnTargetDied(Unit* mTarget)
{
if (_unit->GetHealthPct() > 0)
{
int RandomSpeach;
sRand.randInt(1000);
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)
{
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->SetAIState(STATE_IDLE);
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
DemonSoundRand = false;
DemonPhaseTimer = 5;
DemonPhase = 0;
m_phase = 0;
if (m_phase == 4)
{
DemonPhase = 76;
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(250);
DemonSoundRand = false;
}
//_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
//RemoveAIUpdateEvent();
}
void OnDied(Unit * mKiller)
{
if (m_phase == 2)
{
_unit->GetAIInterface()->m_moveFly = true;
_unit->Emote(EMOTE_ONESHOT_LAND);
}
DemonSoundRand = false;
DemonPhaseTimer = 30;
DemonPhase = 0;
m_phase = 0;
RemoveAIUpdateEvent();
if (!DeathEvent && MaievDialog >= 28 && Maiev && 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, U_FIELD_FLAG_UNIT_UNTACKABLE_SELECT);
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->SetAIState(STATE_IDLE);
_unit->GetAIInterface()->disable_melee = true;
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
_unit->GetAIInterface()->SetNextTarget(NULL);
_unit->GetAIInterface()->m_canMove = false;
_unit->SetUInt32Value(UNIT_FIELD_HEALTH,1);
_unit->GetAIInterface()->StopMovement(0); // needed?
if(_unit->GetCurrentSpell() != NULL)
_unit->GetCurrentSpell()->cancel();
_unit->WipeTargetList();
_unit->WipeHateList();
Maiev->GetAIInterface()->SetAIState(STATE_IDLE);
Maiev->WipeTargetList();
Maiev->WipeHateList();
DeathEvent = 1;
m_phase = 0;
/*RemoveAIUpdateEvent();
RegisterAIUpdateEvent(1000);*/
}
}
void AIUpdate()
{
if (_unit->CombatStatus.IsInCombat())
{
if (DemonPhase > 0 && DemonPhase < 75) // 0;9
{
DemonTrans();
}
if (DemonPhase > 75 && DemonPhase < 134) // 9;17
{
TransRevert();
}
else
{
if (m_phase == 1) // First Phase (without demon form)
{
PhaseOne();
}
if (m_phase == 2) // Second Phase (Fly phase)
{
PhaseTwo();
}
if (m_phase == 3) // Third Phase normal form with ability to change into Demon
{
PhaseThree();
}
if (m_phase == 4) // Fourth Phase Demon Form
{
PhaseFour();
}
if (m_phase == 5) // Fifth Phase with ability to change into Demon and Enrage
{
PhaseFive();
}
}
}
}
void PhaseOne()
{
if (_unit->GetHealthPct() <= 65)
{
_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, U_FIELD_FLAG_UNIT_UNTACKABLE_SELECT);
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
_unit->GetAIInterface()->disable_melee = true;
_unit->GetAIInterface()->m_moveFly = true;
if(_unit->GetCurrentSpell() != NULL)
_unit->GetCurrentSpell()->cancel();
_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);
BladesEvent = 1;
FoADeaths = 2;
m_phase = 2;
}
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)sRand.rand(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)
_unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_FLAME_OF_AZZINOTH, 672.039246f, 326.748322f,
354.206390f, 0.207343f, true, false, 0, 0);
_unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_FLAME_OF_AZZINOTH, 673.008667f, 283.813660f,
354.267548f, 6.203853f, true, false, 0, 0);
}
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:
{
_unit->CastSpellAoF(676.717346f, 322.445251f, 354.153320f, dbcSpell.LookupEntry(THROW_GLAIVE1), false);
_unit->CastSpellAoF(677.368286f, 285.374725f, 354.242157f, dbcSpell.LookupEntry(THROW_GLAIVE1), false);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
}break;
case 14: // Blades spawn
{
Blade1 = _unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_BLADE_OF_AZZINOTH, 676.717346f, 322.445251f, 354.153320f, 5.732623f, true, false, 0, 0);
Blade2 = _unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_BLADE_OF_AZZINOTH, 677.368286f, 285.374725f, 354.242157f, 5.645614f, true, false, 0, 0);
Blade1->SetUInt64Value(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_NO_SELECT);
Blade2->SetUInt64Value(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_NO_SELECT);
Blade1->GetAIInterface()->SetAllowedToEnterCombat(false);
Blade2->GetAIInterface()->SetAllowedToEnterCombat(false);
//Tear of Azzinoth Summon Channel
}break;
case 18: // Flames of Azzinoth Spawn + channeling
{
FoASummon();
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(1000);
}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;
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME));
DemonPhaseTimer = 30;
MaievDialog = 0;
m_currentWP = 0;
m_phase = 3;
}break;
}
if (BladesEvent != 3)
BladesEvent++;
}
if (!FoADeaths)
{
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_SELECT);
_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(2);
FoADeaths = 2;
}
else if (m_currentWP != 2 && _unit->GetAIInterface()->getMoveType() != MOVEMENTTYPE_WANTEDWP && BladesEvent == 20)
{// when he targets any player he enters combat mode which is incorrect with his flag (player can attack him after targeting) and when I added here flag to make him untackable he couldn't cast spells correctly
if (_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
{
Unit* target = NULL;
target = _unit->GetAIInterface()->GetNextTarget();
int Spell = rand()%100;
if (Spell >= 0 && Spell <= 25) // dunno why it doesn't make dmg, but looks correctly (it does damage when target can get into combat mode)
{
_unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[11].info, spells[11].instant);
}
if (Spell > 25 && Spell <= 35)
{
_unit->CastSpell(target, spells[12].info, spells[12].instant);
}
}
}
}
void PhaseThree()
{
if (_unit->GetHealthPct() <= 30 && !MaievDialog && (DemonPhase <= 0 || DemonPhase >= 135 && !_unit->GetCurrentSpell())) // add more stuff with maiev in future!
{
#ifdef USE_SHADOW_PRISON
_unit->CastSpell(_unit, spells[7].info, spells[7].instant);
#endif
_unit->SetUInt64Value(UNIT_FIELD_FLAGS, U_FIELD_FLAG_UNIT_UNTACKABLE_SELECT);
_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
_unit->GetAIInterface()->SetAIState(STATE_SCRIPTIDLE);
_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 && MaievDialog < 32 && (DemonPhase <= 0 || DemonPhase >= 135))
{ // add her weapon switching (from belt to hand, emote cases etc.)
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 11: // 12
{
SpawnMaiev();
Maiev->GetAIInterface()->SetNextTarget(_unit);
Maiev->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Their fury pales before mine, Illidan. We have some unsettled business between us.");
Maiev->PlaySoundToSet(11491);
_unit->GetAIInterface()->SetNextTarget(Maiev);
//_unit->SetFacing(5.287312f); // I must think about good formula for both units
//_unit->GetAIInterface()->setInFront(Maiev); // dunno why it doesn't work -.-'
}break;
case 12: // 13
{
Maiev->CastSpell(_unit, dbcSpell.LookupEntry(TELEPORT), true);
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 29: // 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;
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 = 30;
EnrageTimer = 10;
m_phase = 5;
}break;
}
MaievDialog++;
}
else
{
DemonPhaseTimer--;
if (!DemonPhaseTimer)
{
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
_unit->GetAIInterface()->disable_melee = true;
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)sRand.rand(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->CastSpell(_unit, spells[8].info, spells[8].instant);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
//_unit->GetAIInterface()->disable_melee = true;
}break;
case 13:
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Behold the power... of the demon within!");
_unit->PlaySoundToSet(11475);
_unit->CastSpell(_unit, spells[9].info, spells[9].instant);
}break;
case 33:
{
_unit->SetUInt32Value(UNIT_FIELD_DISPLAYID , 21322);
_unit->SetFloatValue(OBJECT_FIELD_SCALE_X , 5.0f);
}break;
case 43:
{
_unit->CastSpell(_unit, spells[10].info, spells[10].instant);
//_unit->Emote(EMOTE_ONESHOT_CUSTOMSPELL04);
//_unit->RemoveAura(40398);
}break;
case 59:
{
_unit->CastSpell(_unit, spells[10].info, spells[10].instant);
//_unit->RemoveAura(40510);
}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->RemoveAura(40510);
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME));
DemonSoundRand = false;
DemonPhaseTimer = 0;
DemonPhase = 74;
m_phase = 4;
}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->CastSpell(_unit, spells[8].info, spells[8].instant);
_unit->GetAIInterface()->m_canMove = false;
//_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 403);
//_unit->Emote(EMOTE_ONESHOT_CUSTOMSPELL02);
}break;
case 84: //85
{
_unit->CastSpell(_unit, spells[9].info, spells[9].instant);
//_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 404);
}break;
case 108: //108 //109
{
_unit->SetUInt32Value(UNIT_FIELD_DISPLAYID , 21137);
_unit->SetFloatValue(OBJECT_FIELD_SCALE_X , 1.5f);
}break;
case 114: //116 //117
{
_unit->CastSpell(_unit, spells[10].info, spells[10].instant);
//_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 405);
//_unit->Emote(EMOTE_ONESHOT_CUSTOMSPELL04);
}break;
case 125: //122 //125 //123 - hand show //125 - on rage showing lol //126
{
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 1);
}break;
case 129: //133 //129 //130
{
_unit->GetAIInterface()->disable_melee = false;
_unit->GetAIInterface()->m_canMove = true;
_unit->RemoveAura(40510);
if (!MaievDialog)
m_phase = 3;
else
{
EnrageTimer = rand()%10+11;
m_phase = 5;
}
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME));
DemonPhaseTimer = 30;
DemonPhase = 135;
//_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_READY1H);
//_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
}break;
}
DemonPhase++;
}
void PhaseFour()
{
DemonPhaseTimer++;
if (DemonPhaseTimer == 15)
{
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(250);
DemonSoundRand = false;
DemonPhase = 76;
}
if (DemonPhaseTimer < 2 && MaievDialog && !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;
}
}
if (_unit->GetHealthPct() <= 30 && !MaievDialog)
{
RemoveAIUpdateEvent();
RegisterAIUpdateEvent(250);
DemonSoundRand = false;
DemonPhase = 76;
}
else
{
if (_unit->GetAIInterface()->GetNextTarget() && DemonPhase == 75)
{
Unit *target = NULL;
target = _unit->GetAIInterface()->GetNextTarget();
if (_unit->GetDistance2dSq(target) >= 0.0f && _unit->GetDistance2dSq(target) <= 10000.0f)
{
_unit->GetAIInterface()->m_canMove = false;
if (_unit->GetCurrentSpell()) return;
int Spell = rand()%100;
if (Spell >= 0 && Spell <= 80)
_unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[5].info, spells[5].instant);
if (Spell > 80 && Spell <= 90) return;
//_unit->CastSpell(_unit, spells[6].info, spells[6].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()->m_canMove = true;
}
}
}
void PhaseFive()
{
DemonPhaseTimer--;
EnrageTimer--;
if (!DemonPhaseTimer)
{
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
_unit->GetAIInterface()->disable_melee = true;
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[4].info, spells[4].instant);
}
else
{
if (DemonPhase < 1 || DemonPhase > 134)
{
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_READY1H);
float val = (float)sRand.rand(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++)
{
spells[i].casttime--;
if (m_spellcheck[i])
{
spells[i].casttime = spells[i].cooldown;
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;
}
if (spells[i].speech != "")
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, spells[i].speech.c_str());
_unit->PlaySoundToSet(spells[i].soundid);
}
m_spellcheck[i] = false;
return;
}
if ((val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger)) || !spells[i].casttime)
{
_unit->setAttackTimer(spells[i].attackstoptimer, false);
m_spellcheck[i] = true;
}
comulativeperc += spells[i].perctrigger;
}
}
}
void SpawnMaiev() // this doesn't have collision checks! so keep in mind that Maiev can be spawned behind walls!
{
float xchange = (float)sRand.rand(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);
}
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)
{
switch(iWaypointId)
{
case 1:
{
_unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
_unit->GetAIInterface()->SetAIState(STATE_SCRIPTIDLE);
_unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
_unit->GetAIInterface()->setWaypointToMove(0);
BladesEvent = 4;
}break;
case 2:
{
_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;
m_currentWP = 2;
}break;
}
}
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:
bool DemonSoundRand;
int DemonPhaseTimer;
uint32 m_currentWP;
int EnrageTimer;
int DemonPhase;
int nrspells;
Unit* Blade1;
Unit* Blade2;
};
void SetupBlackTemple(ScriptMgr * mgr)
{
GossipScript * AG = (GossipScript*) new AkamaGossip();
mgr->register_gossip_script(CN_AKAMA, AG);
mgr->register_creature_script(CN_FLAME_OF_AZZINOTH, &FlameOfAzzinothAI::Create);
mgr->register_creature_script(CN_AKAMA, &AkamaAI::Create);
mgr->register_creature_script(CN_MAIEV, &MaievAI::Create);
mgr->register_creature_script(CN_BLADE_OF_AZZINOTH, &BladeOfAzzinothAI::Create);
mgr->register_creature_script(CN_FLAME_CRASH, &FlameCrashAI::Create);
mgr->register_creature_script(CN_ILLIDAN_STORMRAGE, &IllidanStormrageAI::Create);
}
Re: [ASCENT] illidan problem and object problem
well the script need to get compiled, moon++ also offers a replacement of the scriptsolution (which produces those files in script_bin). there is a readme which describes how to use it.
but my suggestion is, some repacker should include this. its of much fun to anyone.
t4k