[svn] Update magisters terrace script. Patch provided by streetrat.

--HG--
branch : trunk
This commit is contained in:
megamage
2008-10-30 09:25:38 -05:00
parent a1131cdb21
commit f2f73ff19f
7 changed files with 512 additions and 154 deletions
@@ -24,6 +24,7 @@ EndScriptData */
#include "precompiled.h"
#include "def_magisters_terrace.h"
#include "WorldPacket.h"
#include "ObjectMgr.h"
/*** Spells ***/
@@ -34,6 +35,7 @@ EndScriptData */
#define SPELL_PHOENIX 44194 // Summons a phoenix (Doesn't work?)
#define SPELL_PHOENIX_BURN 44198 // A spell Phoenix uses to damage everything around
#define SPELL_PHOENIX_FIREBALL 44202 // Phoenix casts this in phase 2 and stops moving
#define SPELL_FLAMESTRIKE1_NORMAL 44190 // Damage part
#define SPELL_FLAMESTRIKE1_HEROIC 46163 // Heroic damage part
@@ -81,11 +83,14 @@ EndScriptData */
#define SOUND_DEATH 12421
/** Locations **/
float KaelLocations[3][2]=
float KaelLocations[6][2]=
{
{148.744659, 181.377426},
{140.823883, 195.403046},
{156.574188, 195.650482},
{148.744659, 181.377426},//center
{140.823883, 195.403046},//phoenixpos1
{156.574188, 195.650482},//phoenixpos2
{149.813, 160.917},//spherepos1
{167.223, 173.594},//spherepos2
{130.68, 173.007},//spherepos3
};
#define LOCATION_Z -16.727455
@@ -142,13 +147,34 @@ struct TRINITY_DLL_DECL boss_felblood_kaelthasAI : public ScriptedAI
Phase = 0;
if(pInstance)
pInstance->SetData(DATA_KAELTHAS_EVENT, 0);
{
if(m_creature->isDead())
pInstance->SetData(DATA_KAELTHAS_EVENT, DONE);
else
pInstance->SetData(DATA_KAELTHAS_EVENT, NOT_STARTED);
}
}
void KilledUnit(Unit* victim)
{
if(victim && (victim->GetTypeId() == TYPEID_PLAYER))
{
victim->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY);
victim->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT);
WorldPacket data(12);
data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY);
data.append(victim->GetPackGUID());
data << uint32(0);
victim->SendMessageToSet(&data, true);
}
}
void JustDied(Unit *killer)
{
RemoveGravityLapse();
DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL);
DoPlaySoundToSet(m_creature,SOUND_DEATH);
if(pInstance)
pInstance->SetData(DATA_KAELTHAS_EVENT, DONE);
}
void DamageTaken(Unit* done_by, uint32 &damage)
@@ -161,6 +187,8 @@ struct TRINITY_DLL_DECL boss_felblood_kaelthasAI : public ScriptedAI
{
DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL);
DoPlaySoundToSet(m_creature,SOUND_AGGRO);
if(pInstance)
pInstance->SetData(DATA_KAELTHAS_EVENT, IN_PROGRESS);
}
void SetThreatList(Creature* SummonedUnit)
@@ -175,74 +203,100 @@ struct TRINITY_DLL_DECL boss_felblood_kaelthasAI : public ScriptedAI
if(pUnit && pUnit->isAlive())
{
float threat = m_creature->getThreatManager().getThreat(pUnit);
SummonedUnit->AddThreat(pUnit, threat);
SummonedUnit->AddThreat(pUnit, 0.1f);
}
}
}
void EnterEvadeMode()
{
RemoveGravityLapse();
m_creature->InterruptNonMeleeSpells(true);
m_creature->RemoveAllAuras();
m_creature->DeleteThreatList();
m_creature->CombatStop();
m_creature->LoadCreaturesAddon();
if( m_creature->isAlive() )
m_creature->GetMotionMaster()->MoveTargetedHome();
m_creature->SetLootRecipient(NULL);
InCombat = false;
Reset();
}
void TeleportPlayersToSelf()
{
float x = KaelLocations[0][0];
float y = KaelLocations[0][1];
m_creature->Relocate(x, y, LOCATION_Z, 0);
//m_creature->SendMonsterMove(x, y, LOCATION_Z, 0, 0, 0); // causes some issues...
std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin();
for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();++i)
{
Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid());
if(pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER))
pUnit->CastSpell(pUnit, SPELL_TELEPORT_CENTER, true);
float x,y,z;
m_creature->Relocate(KaelLocations[0][0], KaelLocations[0][1], LOCATION_Z, 0);
Map *map = m_creature->GetMap();
InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers();
InstanceMap::PlayerList::const_iterator i;
for (i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
//if(!(*i)->isGameMaster())
if((*i) && (*i)->isAlive())
{
(*i)->CastSpell((*i), SPELL_TELEPORT_CENTER, true);
m_creature->GetNearPoint(m_creature,x,y,z,5,5,0);
(*i)->TeleportTo(m_creature->GetMapId(),x,y,LOCATION_Z,(*i)->GetOrientation());
}
}
DoCast(m_creature, SPELL_TELEPORT_CENTER, true);
}
void CastGravityLapseKnockUp()
{
std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin();
for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();++i)
{
Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid());
if(pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER))
Map *map = m_creature->GetMap();
InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers();
InstanceMap::PlayerList::const_iterator i;
for (i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if((*i) && (*i)->isAlive())
// Knockback into the air
pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_DOT, true, 0, 0, m_creature->GetGUID());
(*i)->CastSpell((*i), SPELL_GRAVITY_LAPSE_DOT, true, 0, 0, m_creature->GetGUID());
}
}
void CastGravityLapseFly() // Use Fly Packet hack for now as players can't cast "fly" spells unless in map 530. Has to be done a while after they get knocked into the air...
{
std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin();
for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();++i)
{
Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid());
if(pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER))
Map *map = m_creature->GetMap();
InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers();
InstanceMap::PlayerList::const_iterator i;
for (i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if((*i) && (*i)->isAlive())
{
// Also needs an exception in spell system.
pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_FLY, true, 0, 0, m_creature->GetGUID());
(*i)->CastSpell((*i), SPELL_GRAVITY_LAPSE_FLY, true, 0, 0, m_creature->GetGUID());
// Use packet hack
WorldPacket data(12);
data.SetOpcode(SMSG_MOVE_SET_CAN_FLY);
data.append(pUnit->GetPackGUID());
data.append((*i)->GetPackGUID());
data << uint32(0);
pUnit->SendMessageToSet(&data, true);
(*i)->SendMessageToSet(&data, true);
(*i)->SetSpeed(MOVE_FLY, 2.0f);
}
}
}
void RemoveGravityLapse()
{
std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin();
for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();++i)
{
Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid());
if(pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER))
Map *map = m_creature->GetMap();
InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers();
InstanceMap::PlayerList::const_iterator i;
for (i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if((*i))
{
pUnit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY);
pUnit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT);
(*i)->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY);
(*i)->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT);
WorldPacket data(12);
data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY);
data.append(pUnit->GetPackGUID());
data.append((*i)->GetPackGUID());
data << uint32(0);
pUnit->SendMessageToSet(&data, true);
(*i)->SendMessageToSet(&data, true);
}
}
}
@@ -278,11 +332,24 @@ struct TRINITY_DLL_DECL boss_felblood_kaelthasAI : public ScriptedAI
uint32 random = rand()%2 + 1;
float x = KaelLocations[random][0];
float y = KaelLocations[random][1];
Creature* Phoenix = m_creature->SummonCreature(CREATURE_PHOENIX, x, y, LOCATION_Z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
Creature* Phoenix = m_creature->SummonCreature(CREATURE_PHOENIX, x, y, LOCATION_Z, 0, TEMPSUMMON_CORPSE_DESPAWN, 60000);
if(Phoenix)
{
Phoenix->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE);
SetThreatList(Phoenix);
Unit *target = SelectUnit(SELECT_TARGET_RANDOM,1);
if(target)
{
Phoenix->AddThreat(target,1000);
Phoenix->Attack(target,true);
Phoenix->GetMotionMaster()->MoveChase(target);
}
else
{
Phoenix->AddThreat(m_creature->getVictim(),1000);
Phoenix->Attack(m_creature->getVictim(),true);
Phoenix->GetMotionMaster()->MoveChase(m_creature->getVictim());
}
}
DoYell(SAY_PHOENIX, LANG_UNIVERSAL, NULL);
@@ -296,6 +363,7 @@ struct TRINITY_DLL_DECL boss_felblood_kaelthasAI : public ScriptedAI
Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0);
if(target)
{
m_creature->InterruptNonMeleeSpells(false);
DoCast(target, SPELL_FLAMESTRIKE3, true);
FlameStrikeTimer = 20000 + rand()%5000;
@@ -321,6 +389,7 @@ struct TRINITY_DLL_DECL boss_felblood_kaelthasAI : public ScriptedAI
case 1:
{
m_creature->StopMoving();
if(GravityLapseTimer < diff)
{
switch(GravityLapsePhase)
@@ -343,6 +412,7 @@ struct TRINITY_DLL_DECL boss_felblood_kaelthasAI : public ScriptedAI
DoYell(SAY_RECAST_GRAVITY,LANG_UNIVERSAL,NULL);
DoPlaySoundToSet(m_creature,SOUND_RECAST_GRAVITY);
}
m_creature->StopMoving();
DoCast(m_creature, SPELL_GRAVITY_LAPSE_INITIAL);
GravityLapseTimer = 2000 + diff;// Don't interrupt the visual spell
GravityLapsePhase = 1;
@@ -365,9 +435,29 @@ struct TRINITY_DLL_DECL boss_felblood_kaelthasAI : public ScriptedAI
GravityLapseTimer = 30000;
GravityLapsePhase = 4;
for(uint8 i = 0; i < 3; ++i)
{
Creature* Orb = DoSpawnCreature(CREATURE_ARCANE_SPHERE, 5, 5, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
if(Orb) SetThreatList(Orb);
{
Creature* Orb = m_creature->SummonCreature(CREATURE_ARCANE_SPHERE,KaelLocations[3+i][0],KaelLocations[3+i][1],LOCATION_Z,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,30000);
if(Orb)
{
SetThreatList(Orb);
Unit *target = SelectUnit(SELECT_TARGET_BOTTOMAGGRO,i);
if(target)
{
Orb->AddThreat(target,1000);
Orb->Attack(target,true);
Orb->GetMotionMaster()->MoveChase(target);
}
else
{
Unit *ntarget = SelectUnit(SELECT_TARGET_RANDOM,0);
if(ntarget)
{
Orb->AddThreat(ntarget,1000);
Orb->Attack(ntarget,true);
Orb->GetMotionMaster()->MoveChase(ntarget);
}
}
}
}
DoCast(m_creature, SPELL_GRAVITY_LAPSE_CHANNEL);
break;
@@ -426,96 +516,149 @@ struct TRINITY_DLL_DECL mob_felkael_flamestrikeAI : public ScriptedAI
struct TRINITY_DLL_DECL mob_felkael_phoenixAI : public ScriptedAI
{
mob_felkael_phoenixAI(Creature *c) : ScriptedAI(c) {Reset();}
mob_felkael_phoenixAI(Creature *c) : ScriptedAI(c)
{
pInstance = ((ScriptedInstance*)c->GetInstanceData());
Reset();
}
uint32 BurnTimer;
uint32 CheckTimer;
uint8 phase;
ScriptedInstance* pInstance;
bool end;
void Reset()
{
m_creature->SetSpeed(MOVE_RUN, 0.5f);
m_creature->SetSpeed(MOVE_WALK, 0.5f);
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE);
BurnTimer = 2000;
CheckTimer = 1000;
phase = 0;
end = false;
}
void Aggro(Unit* who) {}
void JustDied(Unit* slayer)
{
DoSpawnCreature(CREATURE_PHOENIX_EGG, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000);
if (end)
return;
DoSpawnCreature(CREATURE_PHOENIX_EGG, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 45000);
}
void UpdateAI(const uint32 diff)
{
if(CheckTimer < diff)
{
if (pInstance)
{
Creature *boss = ((Creature*)Unit::GetUnit((*m_creature),pInstance->GetData64(DATA_KAEL)));
if (boss)
{
phase = ((boss_felblood_kaelthasAI*)boss->AI())->Phase;
if(boss->isDead() || !boss->isInCombat())
{
end = true;
m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_FIRE, NULL, false);//temphack, hellfire is not damaging self
}
}
}
CheckTimer = 1000;
}else CheckTimer -= diff;
if (!m_creature->SelectHostilTarget() || !m_creature->getVictim())
return;
if (BurnTimer < diff)
{
DoCast(m_creature->getVictim(), SPELL_PHOENIX_BURN);
BurnTimer = 2000;
}else BurnTimer -= diff;
if (BurnTimer < diff)
{
if(!phase)
{
DoCast(m_creature, SPELL_PHOENIX_BURN);
m_creature->DealDamage(m_creature, 1500, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_FIRE, NULL, false);//temphack, hellfire is not damaging self
}
else
{
m_creature->StopMoving();
DoCast(m_creature->getVictim(), SPELL_PHOENIX_FIREBALL);
}
BurnTimer = 2000;
}else BurnTimer -= diff;
DoMeleeAttackIfReady();
//DoMeleeAttackIfReady();
}
};
struct TRINITY_DLL_DECL mob_felkael_phoenix_eggAI : public ScriptedAI
struct TRINITY_DLL_DECL mob_felkael_phoenix_eggAI : public Scripted_NoMovementAI
{
mob_felkael_phoenix_eggAI(Creature *c) : ScriptedAI(c) {Reset();}
mob_felkael_phoenix_eggAI(Creature *c) : Scripted_NoMovementAI(c)
{
pInstance = ((ScriptedInstance*)c->GetInstanceData());
Reset();
}
uint32 HatchTimer;
ScriptedInstance* pInstance;
void Reset() { HatchTimer = 15000; }
void Aggro(Unit* who) {}
void MoveInLineOfSight(Unit* who) {}
void UpdateAI(const uint32 diff)
{
if(HatchTimer < diff)
{
DoSpawnCreature(CREATURE_PHOENIX, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000);
m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
}else HatchTimer -= diff;
Creature *bird = DoSpawnCreature(CREATURE_PHOENIX, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 60000);
if (bird)
{
Unit *boss = Unit::GetUnit((*m_creature),pInstance->GetData64(DATA_KAEL));
if (boss && boss->getVictim())
{
bird->AddThreat(boss->getVictim(),100);
bird->Attack(boss->getVictim(),true);
bird->GetMotionMaster()->MoveChase(boss->getVictim());
}
}
m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
}else HatchTimer -= diff;
}
};
struct TRINITY_DLL_DECL mob_arcane_sphereAI : public ScriptedAI
{
mob_arcane_sphereAI(Creature *c) : ScriptedAI(c) {Reset();}
mob_arcane_sphereAI(Creature *c) : ScriptedAI(c)
{
pInstance = ((ScriptedInstance*)c->GetInstanceData());
Reset();
}
uint32 DespawnTimer;
uint32 ChangeTargetTimer;
uint32 CheckTimer;
bool TargetLocked;
ScriptedInstance* pInstance;
void Reset()
{
m_creature->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING);
DespawnTimer = 30000;
ChangeTargetTimer = 5000;
TargetLocked = false;
CheckTimer = 1000;
m_creature->SetSpeed(MOVE_RUN, 0.5f);
m_creature->SetSpeed(MOVE_WALK, 0.5f);
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
m_creature->setFaction(14);
DoCast(m_creature, SPELL_ARCANE_SPHERE_PASSIVE, true);
}
void MoveInLineOfSight(Unit* who)
{
if(TargetLocked)
return;
if(who && who->IsHostileTo(m_creature) && (m_creature->IsWithinDistInMap(who, 25)))
StalkTarget(who);
}
void Aggro(Unit* who) {}
void StalkTarget(Unit* target)
{
if(!target)
return;
m_creature->GetMotionMaster()->MoveChase(target);
TargetLocked = true;
m_creature->AddThreat(target,100000);
m_creature->GetMotionMaster()->MoveChase(target);
m_creature->Attack(target,true);
}
void UpdateAI(const uint32 diff)
@@ -525,16 +668,63 @@ struct TRINITY_DLL_DECL mob_arcane_sphereAI : public ScriptedAI
else DespawnTimer -= diff;
if(!m_creature->getVictim() || !m_creature->SelectHostilTarget())
return;
ChangeTargetTimer = 0;
if(ChangeTargetTimer < diff)
{
TargetLocked = false;
DoResetThreat();
Unit *ntarget = SelectUnit(SELECT_TARGET_RANDOM,0);
if (ntarget)
StalkTarget(ntarget);
ChangeTargetTimer = 10000;
}else ChangeTargetTimer -= diff;
if(CheckTimer < diff)
{
if (pInstance)
{
Creature *boss = (Creature*)Unit::GetUnit((*m_creature),pInstance->GetData64(DATA_KAEL));
if(boss)
{
if(!((boss_felblood_kaelthasAI*)boss->AI())->Phase || boss->isDead())
DespawnTimer = 0;
}else DespawnTimer = 0;
}
CheckTimer = 1000;
}else CheckTimer -= diff;
}
};
bool GOHello_go_kael_orb(Player *player, GameObject* _GO)
{
ScriptedInstance* pInst = (ScriptedInstance*)_GO->GetInstanceData();
if (pInst && player)
{
Unit *kael = Unit::GetUnit((*_GO),pInst->GetData64(DATA_KAEL));
if (kael && kael->isDead())
player->TeleportTo(530, 12888, -6876, 9, 0.3);
}
return true;
}
bool GOHello_go_movie_orb(Player *player, GameObject* _GO)
{
if (player)
{
WorldPacket data(SMSG_TRIGGER_CINEMATIC, 4);
data << (uint32)164;
player->GetSession()->SendPacket(&data);
if (player->GetQuestStatus(11490) == QUEST_STATUS_INCOMPLETE)
{
Unit *qUnit = player->SummonCreature(25042,player->GetPositionX(),player->GetPositionY(),player->GetPositionZ()-10,0,TEMPSUMMON_CORPSE_DESPAWN,0);
if(qUnit)
player->DealDamage(qUnit, qUnit->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
}
}
return true;
}
CreatureAI* GetAI_boss_felblood_kaelthas(Creature* c)
{
return new boss_felblood_kaelthasAI(c);
@@ -587,5 +777,15 @@ void AddSC_boss_felblood_kaelthas()
newscript = new Script;
newscript->Name="mob_felkael_flamestrike";
newscript->GetAI = GetAI_mob_felkael_flamestrike;
m_scripts[nrscripts++] = newscript;
newscript = new Script;
newscript->Name="go_kael_orb";
newscript->pGOHello = &GOHello_go_kael_orb;
m_scripts[nrscripts++] = newscript;
newscript = new Script;
newscript->Name="go_movie_orb";
newscript->pGOHello = &GOHello_go_movie_orb;
m_scripts[nrscripts++] = newscript;
}
@@ -6,12 +6,12 @@
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* ScriptData
@@ -102,8 +102,8 @@ struct TRINITY_DLL_DECL boss_priestess_delrissaAI : public ScriptedAI
{
pInstance = ((ScriptedInstance*)c->GetInstanceData());
Adds.clear();
Reset();
SummonAdds();
//SummonAdds();
Reset();
Heroic = c->GetMap()->IsHeroic();
}
@@ -126,6 +126,7 @@ struct TRINITY_DLL_DECL boss_priestess_delrissaAI : public ScriptedAI
void Reset()
{
m_creature->SetCorpseDelay(60*60*1000);
LackeysKilled = 0;
PlayersKilled = 0;
@@ -139,11 +140,13 @@ struct TRINITY_DLL_DECL boss_priestess_delrissaAI : public ScriptedAI
CheckAdds();
if(pInstance)
{
pInstance->SetData(DATA_DELRISSA_EVENT, NOT_STARTED);
pInstance->SetData(DATA_DELRISSA_DEATH_COUNT, 0);
}
if(pInstance)
{
pInstance->SetData(DATA_DELRISSA_DEATH_COUNT, 0);
if (m_creature->isDead())
pInstance->SetData(DATA_DELRISSA_EVENT, DONE);
else pInstance->SetData(DATA_DELRISSA_EVENT, NOT_STARTED);
}
else error_log(ERROR_INST_DATA);
}
@@ -159,6 +162,8 @@ struct TRINITY_DLL_DECL boss_priestess_delrissaAI : public ScriptedAI
void SummonAdds()
{
/*if (m_creature->isDead())
return;*/
std::vector<uint32> AddList;
for(uint8 i = 0; i < 8; ++i)
AddList.push_back(AddEntry[i]);
@@ -179,31 +184,35 @@ struct TRINITY_DLL_DECL boss_priestess_delrissaAI : public ScriptedAI
void CheckAdds()
{
//if (m_creature->isDead())
// return;
if(Adds.empty())
{
SummonAdds();
return;
}
for(uint8 i = 0; i < Adds.size(); ++i)
{
bool resummon = true;
Creature* pAdd = ((Creature*)Unit::GetUnit(*m_creature, Adds[i]->guid));
if(pAdd && pAdd->isAlive())
{
pAdd->AI()->EnterEvadeMode(); // Force them out of combat and reset if they are in combat.
resummon = false;
}
if(resummon)
pAdd->AI()->EnterEvadeMode();
pAdd->GetMotionMaster()->MovePoint(0,LackeyLocations[i][0], LackeyLocations[i][1], POS_Z);
}
if(!pAdd || (pAdd && pAdd->isDead()))
{
pAdd = m_creature->SummonCreature(Adds[i]->entry, LackeyLocations[i][0], LackeyLocations[i][1], POS_Z, ORIENT, TEMPSUMMON_DEAD_DESPAWN, 0);
Add* nAdd = new Add(Adds[i]->entry, pAdd->GetGUID());
Adds.erase(Adds.begin() + i);
Adds.push_back(nAdd);
}
if(pAdd)
pAdd->RemoveCorpse();//looks stupid if mob is alive but has a dead corpse in front of him :)
Creature* pAdd = m_creature->SummonCreature(Adds[i]->entry, LackeyLocations[i][0], LackeyLocations[i][1], POS_Z, ORIENT, TEMPSUMMON_DEAD_DESPAWN, 0);
if(pAdd)
Adds[i]->guid = pAdd->GetGUID();
}
}
}
void KilledUnit(Unit* victim)
{
if(victim->GetTypeId() != TYPEID_PLAYER)
if(victim->GetTypeId() != TYPEID_PLAYER || m_creature->isDead())
return;
DoYell(PlayerDeath[PlayersKilled].text, LANG_UNIVERSAL, NULL);
@@ -214,10 +223,14 @@ struct TRINITY_DLL_DECL boss_priestess_delrissaAI : public ScriptedAI
void KilledLackey()
{
if(m_creature->isDead())//no sense to talk if dead..
return;
DoYell(LackeyDeath[LackeysKilled].text, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, LackeyDeath[LackeysKilled].sound);
if( LackeysKilled < 3 )
++LackeysKilled;
CheckLootable();
}
void JustDied(Unit* killer)
@@ -241,7 +254,7 @@ struct TRINITY_DLL_DECL boss_priestess_delrissaAI : public ScriptedAI
void CheckLootable()
{
if(LackeysKilled > 4)
if(pInstance && pInstance->GetData(DATA_DELRISSA_DEATH_COUNT) >= 4)
m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
else
m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
@@ -366,7 +379,12 @@ struct TRINITY_DLL_DECL boss_priestess_guestAI : public ScriptedAI
void Reset()
{
UsedPotion = false;
if(pInstance)
{
Creature *boss = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_DELRISSA)));
if (boss && boss->isDead())
boss->Respawn();
}
ResetThreatTimer = 5000 + rand()%15000; // These guys like to switch targets often, and are not meant to be tanked.
}
@@ -637,7 +655,9 @@ struct TRINITY_DLL_DECL boss_ellris_duskhallowAI : public boss_priestess_guestAI
Fear_Timer = 10000;
}else Fear_Timer -= diff;
DoMeleeAttackIfReady();
if (m_creature->GetDistance(m_creature->getVictim()) <= 10)
m_creature->StopMoving();
//DoMeleeAttackIfReady();//should not melee, she's a warlock
}
};
@@ -740,7 +760,7 @@ struct TRINITY_DLL_DECL boss_yazzaiAI : public boss_priestess_guestAI
if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() )
return;
boss_priestess_guestAI::UpdateAI(diff);
boss_priestess_guestAI::UpdateAI(diff);
if(Polymorph_Timer < diff)
{
@@ -792,19 +812,29 @@ struct TRINITY_DLL_DECL boss_yazzaiAI : public boss_priestess_guestAI
if(Unit* target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()))
//if in melee range
if (target->IsWithinDistInMap(m_creature, 5))
{
InMeleeRange = true;
break;
}
{
InMeleeRange = true;
break;
}
}
//if anybody is in melee range than escape by blink
if(InMeleeRange)
DoCast(m_creature, SPELL_BLINK);
{
//DoCast(m_creature, SPELL_BLINK); //blink does not work on npcs
float x,y,z;
m_creature->GetPosition(x,y,z);
x = rand()%2 ? x+10+rand()%10 : x-10-rand()%10;
y = rand()%2 ? y+10+rand()%10 : y-10-rand()%10;
m_creature->Relocate(x,y,z);
m_creature->SendMonsterMove(x, y, m_creature->GetPositionZ(), 0,0,0);
}
Blink_Timer = 8000;
}else Blink_Timer -= diff;
DoMeleeAttackIfReady();
if (m_creature->GetDistance(m_creature->getVictim()) <= 10)
m_creature->StopMoving();
//DoMeleeAttackIfReady(); //mage type, no melee needed
}
};
@@ -948,6 +978,8 @@ struct TRINITY_DLL_DECL boss_garaxxasAI : public boss_priestess_guestAI
uint32 Multi_Shot_Timer;
uint32 Wing_Clip_Timer;
uint32 Freezing_Trap_Timer;
uint32 StopMoving;
bool Stopped;
void Reset()
{
@@ -960,6 +992,8 @@ struct TRINITY_DLL_DECL boss_garaxxasAI : public boss_priestess_guestAI
Multi_Shot_Timer = 10000;
Wing_Clip_Timer = 4000;
Freezing_Trap_Timer = 15000;
StopMoving = 2000;
Stopped = false;
boss_priestess_guestAI::Reset();
}
@@ -1030,6 +1064,16 @@ struct TRINITY_DLL_DECL boss_garaxxasAI : public boss_priestess_guestAI
Shoot_Timer = 2500;
}else Shoot_Timer -= diff;
}
if(StopMoving < diff)
{
if(Stopped)
Stopped = false;
else
Stopped = true;
StopMoving = 2000+rand()%5000;
}else StopMoving -= diff;
if (Stopped)
m_creature->StopMoving();
}
};
@@ -1178,9 +1222,12 @@ struct TRINITY_DLL_DECL boss_zelfanAI : public boss_priestess_guestAI
boss_priestess_guestAI::UpdateAI(diff);
if(Goblin_Dragon_Gun_Timer < diff)
{
DoCast(m_creature->getVictim(), SPELL_GOBLIN_DRAGON_GUN);
Goblin_Dragon_Gun_Timer = 10000;
{
if (m_creature->GetDistance(m_creature->getVictim()) <= 5)
{
Goblin_Dragon_Gun_Timer = 10000;
DoCast(m_creature->getVictim(), SPELL_GOBLIN_DRAGON_GUN);
}else Goblin_Dragon_Gun_Timer = 2000;
}else Goblin_Dragon_Gun_Timer -= diff;
if(Rocket_Launch_Timer < diff)
@@ -89,7 +89,7 @@ struct TRINITY_DLL_DECL boss_selin_fireheartAI : public ScriptedAI
uint32 DrainManaTimer;
uint32 FelExplosionTimer;
uint32 DrainCrystalTimer;
uint32 EmpowerTimer;
uint32 CheckTimer;
bool IsDraining;
bool DrainingCrystal;
@@ -108,27 +108,28 @@ struct TRINITY_DLL_DECL boss_selin_fireheartAI : public ScriptedAI
if(pUnit)
{
if(!pUnit->isAlive())
((Creature*)pUnit)->Respawn(); // Let TrinIty handle setting death state, etc.
((Creature*)pUnit)->Respawn(); // Let MaNGOS handle setting death state, etc.
// Only need to set unselectable flag. You can't attack unselectable units so non_attackable flag is not necessary here.
pUnit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
}
GameObject* Door = GameObject::GetGameObject(*m_creature, pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR));
if( Door )
Door->SetGoState(0); // Open the big encounter door. Close it in Aggro and open it only in JustDied(and here)
// Small door opened after event are expected to be closed by default
// Set Inst data for encounter
pInstance->SetData(DATA_SELIN_EVENT, NOT_STARTED);
if (m_creature->isDead())
pInstance->SetData(DATA_SELIN_EVENT, DONE);
else pInstance->SetData(DATA_SELIN_EVENT, NOT_STARTED);
}else error_log(ERROR_INST_DATA);
DrainLifeTimer = 3000 + rand()%4000;
DrainManaTimer = DrainLifeTimer + 5000;
FelExplosionTimer = 2100;
DrainCrystalTimer = 10000 + rand()%5000;
DrainCrystalTimer = 20000 + rand()%5000;
EmpowerTimer = 10000;
CheckTimer = 1000;
IsDraining = false;
DrainingCrystal = false;
@@ -193,6 +194,7 @@ struct TRINITY_DLL_DECL boss_selin_fireheartAI : public ScriptedAI
void Aggro(Unit* who)
{
m_creature->SetPower(POWER_MANA, 0);
DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_AGGRO);
@@ -262,7 +264,6 @@ struct TRINITY_DLL_DECL boss_selin_fireheartAI : public ScriptedAI
if( ContinueDoor )
ContinueDoor->SetGoState(0); // Open the door leading further in
ShatterRemainingCrystals();
}
void UpdateAI(const uint32 diff)
@@ -286,12 +287,8 @@ struct TRINITY_DLL_DECL boss_selin_fireheartAI : public ScriptedAI
{
if( DrainManaTimer < diff )
{
Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0);
if( target->getPowerType() == POWER_MANA)
{
DoCast(target, SPELL_DRAIN_MANA);
DrainManaTimer = 10000;
}
DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DRAIN_MANA);
DrainManaTimer = 10000;
}else DrainManaTimer -= diff;
}
}
@@ -321,27 +318,35 @@ struct TRINITY_DLL_DECL boss_selin_fireheartAI : public ScriptedAI
{
if( IsDraining )
{
if( EmpowerTimer < diff )
{
IsDraining = false;
DrainingCrystal = false;
if (CheckTimer < diff)
{
Unit* CrystalChosen = Unit::GetUnit(*m_creature, CrystalGUID);
if(CrystalChosen)
{
if(CrystalChosen->GetUInt32Value(UNIT_CHANNEL_SPELL) == SPELL_MANA_RAGE)
{
m_creature->StopMoving();
}else{
IsDraining = false;
DrainingCrystal = false;
DoYell(SAY_EMPOWERED, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_EMPOWERED);
DoYell(SAY_EMPOWERED, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_EMPOWERED);
Unit* CrystalChosen = Unit::GetUnit(*m_creature, CrystalGUID);
if( CrystalChosen && CrystalChosen->isAlive() )
// Use Deal Damage to kill it, not setDeathState.
CrystalChosen->DealDamage(CrystalChosen, CrystalChosen->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
Unit* CrystalChosen = Unit::GetUnit(*m_creature, CrystalGUID);
if( CrystalChosen && CrystalChosen->isAlive() )
// Use Deal Damage to kill it, not setDeathState.
CrystalChosen->DealDamage(CrystalChosen, CrystalChosen->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
CrystalGUID = 0;
CrystalGUID = 0;
m_creature->GetMotionMaster()->Clear();
m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
}else EmpowerTimer -= diff;
}
m_creature->GetMotionMaster()->Clear();
m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
}
}
CheckTimer = 1000;
}else CheckTimer -= diff;
}
}
DoMeleeAttackIfReady(); // No need to check if we are draining crystal here, as the spell has a stun.
}
};
@@ -363,6 +368,7 @@ struct TRINITY_DLL_DECL mob_fel_crystalAI : public ScriptedAI
void JustDied(Unit* killer)
{
m_creature->RemoveAurasDueToSpell(SPELL_MANA_RAGE);
if(ScriptedInstance* pInstance = ((ScriptedInstance*)m_creature->GetInstanceData()))
{
Creature* Selin = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_SELIN)));
@@ -370,10 +376,10 @@ struct TRINITY_DLL_DECL mob_fel_crystalAI : public ScriptedAI
{
if(((boss_selin_fireheartAI*)Selin->AI())->CrystalGUID == m_creature->GetGUID())
{
Selin->RemoveAurasDueToSpell(SPELL_MANA_RAGE);
// Set this to false if we are the creature that Selin is draining so his AI flows properly
((boss_selin_fireheartAI*)Selin->AI())->DrainingCrystal = false;
((boss_selin_fireheartAI*)Selin->AI())->IsDraining = false;
((boss_selin_fireheartAI*)Selin->AI())->EmpowerTimer = 10000;
Selin->RemoveAurasDueToSpell(SPELL_MANA_RAGE);
if(Selin->getVictim())
{
Selin->AI()->AttackStart(Selin->getVictim());
@@ -47,6 +47,7 @@ EndScriptData */
#define SPELL_SUMMON_PURE_ENERGY 44322 //not-working, this script summon this creatures without this spell
#define SPELL_OVERLOAD 44353
#define SPELL_ARCANE_SHOCK 44319
#define ASTRAL_FLARE_VISUAL 30237
//Creatures
#define CREATURE_PURE_ENERGY 24745
@@ -81,7 +82,11 @@ struct TRINITY_DLL_DECL boss_vexallusAI : public ScriptedAI
Enraged = false;
if(pInstance)
pInstance->SetData(DATA_VEXALLUS_EVENT, NOT_STARTED);
{
if (m_creature->isDead())
pInstance->SetData(DATA_VEXALLUS_EVENT, DONE);
else pInstance->SetData(DATA_VEXALLUS_EVENT, NOT_STARTED);
}
}
void KilledUnit(Unit *victim)
@@ -130,7 +135,7 @@ struct TRINITY_DLL_DECL boss_vexallusAI : public ScriptedAI
DoYell(SAY_ENERGY, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_ENERGY);
Creature* PureEnergyCreature = NULL;
PureEnergyCreature = DoSpawnCreature(CREATURE_PURE_ENERGY, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
PureEnergyCreature = DoSpawnCreature(CREATURE_PURE_ENERGY, 10, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
Unit* target = NULL;
target = SelectUnit(SELECT_TARGET_RANDOM, 0);
if (PureEnergyCreature && target)
@@ -138,7 +143,7 @@ struct TRINITY_DLL_DECL boss_vexallusAI : public ScriptedAI
if(Heroic) // *Heroic mode only - he summons two instead of one.
{
PureEnergyCreature = DoSpawnCreature(CREATURE_PURE_ENERGY, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
PureEnergyCreature = DoSpawnCreature(CREATURE_PURE_ENERGY, -10, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
target = SelectUnit(SELECT_TARGET_RANDOM, 0);
if (PureEnergyCreature && target)
PureEnergyCreature->AI()->AttackStart(target);
@@ -186,10 +191,14 @@ struct TRINITY_DLL_DECL mob_pure_energyAI : public ScriptedAI
mob_pure_energyAI(Creature *c) : ScriptedAI(c) {Reset();}
uint32 EnergyBoltTimer;
uint32 VisualTimer;
void Reset()
{
EnergyBoltTimer = 1700;
VisualTimer = 1000;
m_creature->SetSpeed(MOVE_RUN, 0.5f);
m_creature->SetSpeed(MOVE_WALK, 0.5f);
}
void JustDied(Unit* slayer)
@@ -209,6 +218,11 @@ struct TRINITY_DLL_DECL mob_pure_energyAI : public ScriptedAI
DoCast(m_creature->getVictim(), SPELL_ENERGY_BOLT);
EnergyBoltTimer = 1700;
}else EnergyBoltTimer -= diff;
if(VisualTimer < diff)
{
DoCast(m_creature->getVictim(), ASTRAL_FLARE_VISUAL, true);
VisualTimer = 1000;
}else VisualTimer -= diff;
}
};
@@ -25,5 +25,7 @@
#define DATA_DELRISSA_DEATH_COUNT 15
#define DATA_KAEL 16
#define ERROR_INST_DATA "SD2 Error: Instance Data not set properly for Magister's Terrace instance (map 585). Encounters will be buggy."
#endif
@@ -40,12 +40,14 @@ struct TRINITY_DLL_DECL instance_magisters_terrace : public ScriptedInstance
Initialize();
}
uint32 DoorState[3];//0seline, 1vexallus, 2derlissa
uint32 Encounters[NUMBER_OF_ENCOUNTERS];
uint32 DelrissaDeathCount;
std::list<uint64> FelCrystals;
std::list<uint64>::iterator CrystalItr;
uint64 KaelGUID;
uint64 SelinGUID;
uint64 DelrissaGUID;
uint64 VexallusDoorGUID;
@@ -58,6 +60,9 @@ struct TRINITY_DLL_DECL instance_magisters_terrace : public ScriptedInstance
void Initialize()
{
for(uint8 i = 0; i < 3; i++)
DoorState[i] = 1;//1 closed, 0 opened
for(uint8 i = 0; i < NUMBER_OF_ENCOUNTERS; i++)
Encounters[i] = NOT_STARTED;
@@ -65,6 +70,7 @@ struct TRINITY_DLL_DECL instance_magisters_terrace : public ScriptedInstance
DelrissaDeathCount = 0;
KaelGUID = 0;
SelinGUID = 0;
DelrissaGUID = 0;
VexallusDoorGUID = 0;
@@ -103,9 +109,30 @@ struct TRINITY_DLL_DECL instance_magisters_terrace : public ScriptedInstance
{
switch(identifier)
{
case DATA_SELIN_EVENT: Encounters[0] = data; break;
case DATA_VEXALLUS_EVENT: Encounters[1] = data; break;
case DATA_DELRISSA_EVENT: Encounters[2] = data; break;
case DATA_SELIN_EVENT:
Encounters[0] = data;
if(data==DONE)
{
DoorState[0] = 0;
SaveToDB();
}
break;
case DATA_VEXALLUS_EVENT:
Encounters[1] = data;
if(data==DONE)
{
DoorState[1] = 0;
SaveToDB();
}
break;
case DATA_DELRISSA_EVENT:
Encounters[2] = data;
if(data==DONE)
{
DoorState[2] = 0;
SaveToDB();
}
break;
case DATA_KAELTHAS_EVENT: Encounters[3] = data; break;
case DATA_DELRISSA_DEATH_COUNT:
@@ -114,6 +141,30 @@ struct TRINITY_DLL_DECL instance_magisters_terrace : public ScriptedInstance
}
}
const char* Save()
{
std::ostringstream ss;
ss << "S " << DoorState[0] << " " << DoorState[1] << " " << DoorState[2];
char* data = new char[ss.str().length()+1];
strcpy(data, ss.str().c_str());
return data;
}
void Load(const char* load)
{
if(!load) return;
std::istringstream ss(load);
char dataHead; // S
uint32 data1, data2, data3;
ss >> dataHead >> data1 >> data2 >> data3;
if(dataHead == 'S')
{
DoorState[0] = data1;
DoorState[1] = data2;
DoorState[2] = data3;
}else error_log("SD2: Magister's Terrace: corrupted save data.");
}
void OnCreatureCreate(Creature *creature, uint32 entry)
{
switch(entry)
@@ -121,6 +172,7 @@ struct TRINITY_DLL_DECL instance_magisters_terrace : public ScriptedInstance
case 24723: SelinGUID = creature->GetGUID(); break;
case 24560: DelrissaGUID = creature->GetGUID(); break;
case 24722: FelCrystals.push_back(creature->GetGUID()); break;
case 24664: KaelGUID = creature->GetGUID(); break;
}
}
@@ -128,12 +180,21 @@ struct TRINITY_DLL_DECL instance_magisters_terrace : public ScriptedInstance
{
switch(go->GetEntry())
{
case 187896: VexallusDoorGUID = go->GetGUID(); break;
case 187896:
VexallusDoorGUID = go->GetGUID();
go->SetGoState(DoorState[1]);
break;
//SunwellRaid Gate 02
case 187979: SelinDoorGUID = go->GetGUID(); break;
case 187979:
SelinDoorGUID = go->GetGUID();
go->SetGoState(DoorState[0]);
break;
//Assembly Chamber Door
case 188065: SelinEncounterDoorGUID = go->GetGUID(); break;
case 187770: DelrissaDoorGUID = go->GetGUID(); break;
case 187770:
DelrissaDoorGUID = go->GetGUID();
go->SetGoState(DoorState[2]);
break;
case 188165: KaelStatue[0] = go->GetGUID(); break;
case 188166: KaelStatue[1] = go->GetGUID(); break;
}
@@ -144,6 +205,7 @@ struct TRINITY_DLL_DECL instance_magisters_terrace : public ScriptedInstance
switch(identifier)
{
case DATA_SELIN: return SelinGUID;
case DATA_KAEL: return KaelGUID;
case DATA_DELRISSA: return DelrissaGUID;
case DATA_VEXALLUS_DOOR: return VexallusDoorGUID;
case DATA_SELIN_DOOR: return SelinDoorGUID;