aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/190_world_scripts.sql7
-rw-r--r--src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp88
-rw-r--r--src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp505
-rw-r--r--src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp665
-rw-r--r--src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/def_serpent_shrine.h2
-rw-r--r--src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp174
6 files changed, 1069 insertions, 372 deletions
diff --git a/sql/updates/190_world_scripts.sql b/sql/updates/190_world_scripts.sql
new file mode 100644
index 00000000000..4e130d8cb41
--- /dev/null
+++ b/sql/updates/190_world_scripts.sql
@@ -0,0 +1,7 @@
+UPDATE creature_template SET ScriptName = 'boss_leotheras_the_blind' WHERE entry = '21215';
+UPDATE creature_template SET ScriptName = 'boss_leotheras_the_blind_demonform' WHERE entry = '21875';
+UPDATE creature_template SET ScriptName = 'mob_greyheart_spellbinder' WHERE entry = '21806';
+UPDATE creature_template SET ScriptName = 'mob_inner_demon' WHERE entry = '21857';
+
+UPDATE creature_template SET ScriptName = 'mob_toxic_sporebat', speed = '1' WHERE entry = '22140';
+UPDATE creature_template SET modelid_A = '11686', modelid_H = '11686', flags_extra = '128' WHERE entry = '22207'; \ No newline at end of file
diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp
index c0fe62fd120..13b8ebbf312 100644
--- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp
+++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp
@@ -56,10 +56,11 @@ EndScriptData */
#define SPELL_ENRAGE 27680 //this spell need verification
#define SPELL_SUMMON_WATER_ELEMENT 36459 //not in use yet(in use ever?)
#define SPELL_ELEMENTAL_SPAWNIN 25035
-//#define SPELL_BLUE_BEAM 38015 //channeled Hydross Beam Helper (not in use yet)
+#define SPELL_BLUE_BEAM /*40227*/38015 //channeled Hydross Beam Helper (not in use yet)
#define ENTRY_PURE_SPAWN 22035
#define ENTRY_TAINTED_SPAWN 22036
+#define ENTRY_BEAM_DUMMY 21934
#define HYDROSS_X -239.439
#define HYDROSS_Y -363.481
@@ -75,14 +76,14 @@ EndScriptData */
struct TRINITY_DLL_DECL boss_hydross_the_unstableAI : public ScriptedAI
{
- boss_hydross_the_unstableAI(Creature *c) : ScriptedAI(c)
+ boss_hydross_the_unstableAI(Creature *c) : ScriptedAI(c), Summons(m_creature)
{
pInstance = ((ScriptedInstance*)c->GetInstanceData());
- Reset();
+ Reset();
}
ScriptedInstance* pInstance;
-
+ uint64 beams[2];
uint32 PosCheck_Timer;
uint32 MarkOfHydross_Timer;
uint32 MarkOfCorruption_Timer;
@@ -92,9 +93,14 @@ struct TRINITY_DLL_DECL boss_hydross_the_unstableAI : public ScriptedAI
uint32 MarkOfCorruption_Count;
uint32 EnrageTimer;
bool CorruptedForm;
+ bool beam;
+ SummonList Summons;
void Reset()
{
+ DeSummonBeams();
+ beams[0] = 0;
+ beams[1] = 0;
PosCheck_Timer = 2500;
MarkOfHydross_Timer = 15000;
MarkOfCorruption_Timer = 15000;
@@ -113,8 +119,41 @@ struct TRINITY_DLL_DECL boss_hydross_the_unstableAI : public ScriptedAI
if (pInstance)
pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, NOT_STARTED);
+ beam = false;
+ Summons.DespawnAll();
}
+ void SummonBeams()
+ {
+ Creature* beamer = m_creature->SummonCreature(ENTRY_BEAM_DUMMY,-258.333,-356.34,22.0499,5.90835,TEMPSUMMON_CORPSE_DESPAWN,0);
+ if(beamer)
+ {
+ beamer->CastSpell(m_creature,SPELL_BLUE_BEAM,true);
+ beamer->SetUInt32Value(UNIT_FIELD_DISPLAYID , 11686); //invisible
+ beamer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ beams[0]=beamer->GetGUID();
+ }
+ beamer = beamer = m_creature->SummonCreature(ENTRY_BEAM_DUMMY,-219.918,-371.308,22.0042,2.73072,TEMPSUMMON_CORPSE_DESPAWN,0);
+ if(beamer)
+ {
+ beamer->CastSpell(m_creature,SPELL_BLUE_BEAM,true);
+ beamer->SetUInt32Value(UNIT_FIELD_DISPLAYID , 11686); //invisible
+ beamer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ beams[1]=beamer->GetGUID();
+ }
+ }
+ void DeSummonBeams()
+ {
+ for(uint8 i=0;i<2;i++)
+ {
+ Creature* mob = (Creature*)Unit::GetUnit(*m_creature,beams[i]);
+ if(mob)
+ {
+ mob->setDeathState(DEAD);
+ mob->RemoveCorpse();
+ }
+ }
+ }
void Aggro(Unit *who)
{
DoScriptText(SAY_AGGRO, m_creature);
@@ -146,11 +185,22 @@ struct TRINITY_DLL_DECL boss_hydross_the_unstableAI : public ScriptedAI
void JustSummoned(Creature* summoned)
{
if (summoned->GetEntry() == ENTRY_PURE_SPAWN)
- summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true);
+ {
+ summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true);
+ summoned->CastSpell(summoned,SPELL_ELEMENTAL_SPAWNIN,true);
+ Summons.Summon(summoned);
+ }
if (summoned->GetEntry() == ENTRY_TAINTED_SPAWN)
- summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
+ {
+ summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
+ summoned->CastSpell(summoned,SPELL_ELEMENTAL_SPAWNIN,true);
+ Summons.Summon(summoned);
+ }
+ }
- summoned->CastSpell(summoned,SPELL_ELEMENTAL_SPAWNIN,true);
+ void SummonedCreatureDespawn(Creature *summon)
+ {
+ Summons.Despawn(summon);
}
void JustDied(Unit *victim)
@@ -162,10 +212,16 @@ struct TRINITY_DLL_DECL boss_hydross_the_unstableAI : public ScriptedAI
if (pInstance)
pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, NOT_STARTED);
+ Summons.DespawnAll();
}
void UpdateAI(const uint32 diff)
{
+ if(!beam)
+ {
+ SummonBeams();
+ beam=true;
+ }
//Return since we have no target
if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() )
return;
@@ -221,12 +277,13 @@ struct TRINITY_DLL_DECL boss_hydross_the_unstableAI : public ScriptedAI
DoScriptText(SAY_SWITCH_TO_CLEAN, m_creature);
DoResetThreat();
+ SummonBeams();
// spawn 4 adds
- DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
- DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
- DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
- DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
+ DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
+ DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
+ DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
+ DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
m_creature->SetMeleeDamageSchool(SPELL_SCHOOL_FROST);
m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true);
@@ -287,12 +344,13 @@ struct TRINITY_DLL_DECL boss_hydross_the_unstableAI : public ScriptedAI
DoScriptText(SAY_SWITCH_TO_CORRUPT, m_creature);
DoResetThreat();
+ DeSummonBeams();
// spawn 4 adds
- DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
- DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
- DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
- DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
+ DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
+ DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
+ DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
+ DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
m_creature->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE);
m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp
index b2c3d64b2a5..27265e3d464 100644
--- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp
+++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp
@@ -24,7 +24,6 @@ EndScriptData */
#include "precompiled.h"
#include "def_serpent_shrine.h"
#include "../../../creature/simple_ai.h"
-#include "Item.h"
#include "Spell.h"
#define SAY_INTRO -1548042
@@ -42,6 +41,7 @@ EndScriptData */
#define SAY_SLAY3 -1548054
#define SAY_DEATH -1548055
+#define SPELL_SURGE 38044
#define SPELL_MULTI_SHOT 38310
#define SPELL_SHOCK_BLAST 38509
#define SPELL_ENTANGLE 38316
@@ -61,12 +61,13 @@ EndScriptData */
#define SPOREBAT_Z 77.176567
#define SPOREBAT_O 5.223932
-#define SHIED_GENERATOR_CHANNEL 19870
-#define ENCHANTED_ELEMENTAL 21958
-#define TAINTED_ELEMENTAL 22009
-#define COILFANG_STRIDER 22056
-#define COILFANG_ELITE 22055
-#define TOXIC_SPOREBAT 22140
+#define SHIED_GENERATOR_CHANNEL 19870
+#define ENCHANTED_ELEMENTAL 21958
+#define TAINTED_ELEMENTAL 22009
+#define COILFANG_STRIDER 22056
+#define COILFANG_ELITE 22055
+#define TOXIC_SPOREBAT 22140
+#define TOXIC_SPORES_TRIGGER 22207
float ElementPos[8][4] =
{
@@ -80,6 +81,30 @@ float ElementPos[8][4] =
{-58.9, -901.6, 21.5, 6}
};
+float ElementWPPos[8][3] =
+{
+ {71.700752, -883.905884, 41.097168},
+ {45.039848, -868.022827, 41.097015},
+ {14.585141, -867.894470, 41.097061},
+ {-25.415508, -906.737732, 41.097061},
+ {-11.801594, -963.405884, 41.097067},
+ {14.556657, -979.051514, 41.097137},
+ {43.466549, -979.406677, 41.097027},
+ {69.945908, -964.663940, 41.097054}
+};
+
+float SporebatWPPos[8][3] =
+{
+ {31.6,-896.3,59.1},
+ {9.1, -913.9, 56},
+ {5.2, -934.4, 52.4},
+ {20.7, -946.9, 49.7},
+ {41, -941.9, 51},
+ {47.7, -927.3, 55},
+ {42.2, -912.4, 51.7},
+ {27, -905.9, 50}
+};
+
float CoilfangElitePos[3][4] =
{
{28.84, -923.28, 42.9, 6},
@@ -107,15 +132,18 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
{
boss_lady_vashjAI (Creature *c) : ScriptedAI(c)
{
- pInstance = ((ScriptedInstance*)c->GetInstanceData());
- Reset();
+ pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL;
+ Intro = false;
+ Reset();
+ CanAttack = false;//must be after reset()
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); //set it only once on creature create (no need do intro if wiped)
}
ScriptedInstance *pInstance;
uint64 ShieldGeneratorChannel[4];
- uint64 AggroTargetGUID;
+ uint32 AggroTimer;
uint32 ShockBlast_Timer;
uint32 Entangle_Timer;
uint32 StaticCharge_Timer;
@@ -127,16 +155,17 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
uint32 CoilfangStrider_Timer;
uint32 SummonSporebat_Timer;
uint32 SummonSporebat_StaticTimer;
- uint32 AggroTimer;
-
uint8 EnchantedElemental_Pos;
uint8 Phase;
bool Entangle;
+ bool InCombat;
bool Intro;
+ bool CanAttack;
void Reset()
{
+ AggroTimer = 19000;
ShockBlast_Timer = 1+rand()%60000;
Entangle_Timer = 30000;
StaticCharge_Timer = 10000+rand()%15000;
@@ -150,23 +179,27 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
SummonSporebat_StaticTimer = 30000;
EnchantedElemental_Pos = 0;
Phase = 0;
- AggroTimer = 19000;
- AggroTargetGUID = 0;
-
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- // Start off unattackable so that the intro is done properly
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
Entangle = false;
- Intro = false;
+ InCombat = false;
+ CanAttack = true;
- if(pInstance)
- pInstance->SetData(DATA_LADYVASHJEVENT, NOT_STARTED);
+ Unit *remo;
+ for(uint8 i = 0; i < 4; i++)
+ {
+ remo = Unit::GetUnit(*m_creature, ShieldGeneratorChannel[i]);
+ if (remo)
+ remo->setDeathState(JUST_DIED);
+ }
+ if(pInstance)
+ pInstance->SetData(DATA_LADYVASHJEVENT, NOT_STARTED);
ShieldGeneratorChannel[0] = 0;
ShieldGeneratorChannel[1] = 0;
ShieldGeneratorChannel[2] = 0;
ShieldGeneratorChannel[3] = 0;
+
+ m_creature->SetCorpseDelay(1000*60*60);
}
//Called when a tainted elemental dies
@@ -176,38 +209,6 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
if(TaintedElemental_Timer > 50000)
TaintedElemental_Timer = 50000;
}
-
- void MoveInLineOfSight(Unit *who)
- {
- if(!who || (!who->isAlive())) return;
-
- if(who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who))
- {
- float attackRadius = m_creature->GetAttackDistance(who);
-
- if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who))
- {
- if(who->HasStealthAura())
- who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
-
- m_creature->AddThreat(who, 1.0f);
- }
-
- if(!InCombat && !Intro && m_creature->IsWithinDistInMap(who, 40.0f) && (who->GetTypeId() == TYPEID_PLAYER))
- {
- if(pInstance)
- pInstance->SetData(DATA_LADYVASHJEVENT, IN_PROGRESS);
-
- m_creature->GetMotionMaster()->Clear(false);
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- DoScriptText(SAY_INTRO, m_creature);
- m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK);
- AggroTargetGUID = who->GetGUID();
- Intro = true;
- }
- }
- }
-
void KilledUnit(Unit *victim)
{
switch(rand()%3)
@@ -226,7 +227,7 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
pInstance->SetData(DATA_LADYVASHJEVENT, DONE);
}
-/* void StartEvent()
+ void StartEvent()
{
switch(rand()%4)
{
@@ -236,13 +237,63 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
case 3: DoScriptText(SAY_AGGRO4, m_creature); break;
}
+ InCombat = true;
Phase = 1;
if(pInstance)
pInstance->SetData(DATA_LADYVASHJEVENT, IN_PROGRESS);
- }*/
+ }
- void Aggro(Unit *who){}
+ void Aggro(Unit *who)
+ {
+ if (pInstance)
+ {
+ //remove old tainted cores to prevent cheating in phase 2
+ Map *map = m_creature->GetMap();
+ InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers();
+ for(InstanceMap::PlayerList::const_iterator i = PlayerList.begin();i != PlayerList.end(); ++i)
+ {
+ if((*i))
+ {
+ (*i)->DestroyItemCount(31088, 1, true);
+ }
+ }
+ }
+ if(Phase != 2)
+ AttackStart(who);
+
+ if(!InCombat)
+ StartEvent();
+ }
+
+ void MoveInLineOfSight(Unit *who)
+ {
+ if (!Intro)
+ {
+ Intro = true;
+ DoScriptText(SAY_INTRO, m_creature);
+ }
+ if (!CanAttack)
+ return;
+ if (!who || m_creature->getVictim())
+ return;
+
+ if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who))
+ {
+ float attackRadius = m_creature->GetAttackDistance(who);
+ if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who))
+ {
+ if(who->HasStealthAura())
+ who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
+
+ if(Phase != 2)
+ AttackStart(who);
+
+ if(!InCombat)
+ StartEvent();
+ }
+ }
+ }
void CastShootOrMultishot()
{
@@ -259,7 +310,6 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
DoCast(m_creature->getVictim(), SPELL_MULTI_SHOT);
break;
}
-
if(rand()%3)
{
switch(rand()%2)
@@ -272,48 +322,29 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
void UpdateAI(const uint32 diff)
{
+ if(!CanAttack && Intro)
+ {
+ if(AggroTimer < diff)
+ {
+ CanAttack = true;
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ AggroTimer=19000;
+ }else
+ {
+ AggroTimer-=diff;
+ return;
+ }
+ }
//to prevent abuses during phase 2
if(Phase == 2 && !m_creature->getVictim() && InCombat)
{
- EnterEvadeMode();
- return;
+ EnterEvadeMode();
+ return;
}
-
//Return since we have no target
if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() )
return;
- //Intro
- if(Intro)
- {
- if(AggroTimer < diff)
- {
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- switch(rand()%4)
- {
- case 0: DoScriptText(SAY_AGGRO1, m_creature); break;
- case 1: DoScriptText(SAY_AGGRO2, m_creature); break;
- case 2: DoScriptText(SAY_AGGRO3, m_creature); break;
- case 3: DoScriptText(SAY_AGGRO4, m_creature); break;
- }
- Phase = 1;
- m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE);
- Intro = false;
- //Begin melee attack if we are within range
- if(AggroTargetGUID && Phase != 2)
- {
- Unit* pUnit = Unit::GetUnit((*m_creature), AggroTargetGUID);
- if(pUnit)
- {
- m_creature->GetMotionMaster()->MoveChase(pUnit);
- AttackStart(pUnit);
- }
- DoZoneInCombat();
- }else EnterEvadeMode();
- }else AggroTimer -= diff;
- }
-
if(Phase == 1 || Phase == 3)
{
//ShockBlast_Timer
@@ -370,15 +401,10 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
//Phase 2 begins when Vashj hits 70%. She will run to the middle of her platform and surround herself in a shield making her invulerable.
Phase = 2;
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
m_creature->GetMotionMaster()->Clear();
m_creature->Relocate(MIDDLE_X, MIDDLE_Y, MIDDLE_Z);
m_creature->SendMonsterMove(MIDDLE_X, MIDDLE_Y, MIDDLE_Z, 0, 0, 0);
- m_creature->RemoveAllAuras();
- // This needs an entry in spell_script_target
- DoCast(m_creature, SPELL_MAGIC_BARRIER, true);
-
Creature *pCreature;
for(uint8 i = 0; i < 4; i++)
{
@@ -386,7 +412,6 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
if (pCreature)
ShieldGeneratorChannel[i] = pCreature->GetGUID();
}
-
DoScriptText(SAY_PHASE2, m_creature);
}
}
@@ -397,7 +422,7 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
if(SummonSporebat_Timer < diff)
{
Creature *Sporebat = NULL;
- Sporebat = m_creature->SummonCreature(TOXIC_SPOREBAT, SPOREBAT_X, SPOREBAT_Y, SPOREBAT_Z, SPOREBAT_O, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ Sporebat = m_creature->SummonCreature(TOXIC_SPOREBAT, SPOREBAT_X, SPOREBAT_Y, SPOREBAT_Z, SPOREBAT_O, TEMPSUMMON_CORPSE_DESPAWN, 0);
if(Sporebat)
{
@@ -412,6 +437,10 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
SummonSporebat_StaticTimer -= 1000;
SummonSporebat_Timer = SummonSporebat_StaticTimer;
+
+ if(SummonSporebat_Timer < 5000)
+ SummonSporebat_Timer = 5000;
+
}else SummonSporebat_Timer -= diff;
}
@@ -465,9 +494,7 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
if(EnchantedElemental_Timer < diff)
{
Creature *Elemental;
- Elemental = m_creature->SummonCreature(ENCHANTED_ELEMENTAL, ElementPos[EnchantedElemental_Pos][0], ElementPos[EnchantedElemental_Pos][1], ElementPos[EnchantedElemental_Pos][2], ElementPos[EnchantedElemental_Pos][3], TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
- if(Elemental)
- Elemental->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ());
+ Elemental = m_creature->SummonCreature(ENCHANTED_ELEMENTAL, ElementPos[EnchantedElemental_Pos][0], ElementPos[EnchantedElemental_Pos][1], ElementPos[EnchantedElemental_Pos][2], ElementPos[EnchantedElemental_Pos][3], TEMPSUMMON_CORPSE_DESPAWN, 0);
if(EnchantedElemental_Pos == 7)
EnchantedElemental_Pos = 0;
@@ -482,12 +509,7 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
{
Creature *Tain_Elemental;
uint32 pos = rand()%8;
- Tain_Elemental = m_creature->SummonCreature(TAINTED_ELEMENTAL, ElementPos[pos][0], ElementPos[pos][1], ElementPos[pos][2], ElementPos[pos][3], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000);
- if(Tain_Elemental)
- {
- Tain_Elemental->GetMotionMaster()->Clear();
- Tain_Elemental->GetMotionMaster()->MoveIdle();
- }
+ Tain_Elemental = m_creature->SummonCreature(TAINTED_ELEMENTAL, ElementPos[pos][0], ElementPos[pos][1], ElementPos[pos][2], ElementPos[pos][3], TEMPSUMMON_DEAD_DESPAWN, 0);
TaintedElemental_Timer = 120000;
}else TaintedElemental_Timer -= diff;
@@ -495,35 +517,37 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
//CoilfangElite_Timer
if(CoilfangElite_Timer < diff)
{
- Creature *CoilfangElite;
uint32 pos = rand()%3;
- CoilfangElite = m_creature->SummonCreature(COILFANG_ELITE, CoilfangElitePos[pos][0], CoilfangElitePos[pos][1], CoilfangElitePos[pos][2], CoilfangElitePos[pos][3], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 45000);
- if(CoilfangElite)
+ Creature* CoilfangElite = NULL;
+ CoilfangElite = m_creature->SummonCreature(COILFANG_ELITE, CoilfangElitePos[pos][0], CoilfangElitePos[pos][1], CoilfangElitePos[pos][2], CoilfangElitePos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ if(CoilfangElite)
{
Unit *target = NULL;
target = SelectUnit(SELECT_TARGET_RANDOM, 0);
if(target)
CoilfangElite->AI()->AttackStart(target);
+ else if(m_creature->getVictim())
+ CoilfangElite->AI()->AttackStart(m_creature->getVictim());
}
-
- CoilfangElite_Timer = 45000+rand()%5000; //wowwiki says 50 seconds, bosskillers says 45
+ CoilfangElite_Timer = 45000+rand()%5000;
}else CoilfangElite_Timer -= diff;
//CoilfangStrider_Timer
if(CoilfangStrider_Timer < diff)
{
- Creature *CoilfangStrider;
uint32 pos = rand()%3;
- CoilfangStrider = m_creature->SummonCreature(COILFANG_STRIDER, CoilfangStriderPos[pos][0], CoilfangStriderPos[pos][1], CoilfangStriderPos[pos][2], CoilfangStriderPos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000);
- if(CoilfangStrider)
+ Creature* CoilfangStrider = NULL;
+ CoilfangStrider = m_creature->SummonCreature(COILFANG_STRIDER, CoilfangStriderPos[pos][0], CoilfangStriderPos[pos][1], CoilfangStriderPos[pos][2], CoilfangStriderPos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ if(CoilfangStrider)
{
Unit *target = NULL;
target = SelectUnit(SELECT_TARGET_RANDOM, 0);
if(target)
CoilfangStrider->AI()->AttackStart(target);
+ else if(m_creature->getVictim())
+ CoilfangStrider->AI()->AttackStart(m_creature->getVictim());
}
-
- CoilfangStrider_Timer = 60000+rand()%10000; //wowwiki says 60 seconds, bosskillers says 60-70
+ CoilfangStrider_Timer = 60000+rand()%10000;
}else CoilfangStrider_Timer -= diff;
//Check_Timer
@@ -535,7 +559,6 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
//set life 50%
m_creature->SetHealth(m_creature->GetMaxHealth()/2);
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
m_creature->RemoveAurasDueToSpell(SPELL_MAGIC_BARRIER);
DoScriptText(SAY_PHASE3, m_creature);
@@ -550,64 +573,114 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI
}
}
};
-
+class TRINITY_DLL_DECL VashjSurgeAura : public Aura
+{
+ public:
+ VashjSurgeAura(SpellEntry *spell, uint32 eff, int32 *bp, Unit *target, Unit *caster) : Aura(spell, eff, bp, target, caster, NULL)
+ {}
+};
//Enchanted Elemental
//If one of them reaches Vashj he will increase her damage done by 5%.
struct TRINITY_DLL_DECL mob_enchanted_elementalAI : public ScriptedAI
{
mob_enchanted_elementalAI(Creature *c) : ScriptedAI(c)
{
- pInstance = ((ScriptedInstance*)c->GetInstanceData());
+ pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL;
Reset();
}
ScriptedInstance *pInstance;
-
- uint32 Check_Timer;
- uint32 Movement_Timer;
+ uint32 move;
+ uint32 phase;
+ float x, y, z;
+ Unit *Vashj;
void Reset()
- {
- Check_Timer = 5000;
- Movement_Timer = 500;
+ {
+ m_creature->SetSpeed(MOVE_WALK,0.6,true);//walk
+ m_creature->SetSpeed(MOVE_RUN,0.6,true);//run
+ move = 0;
+ phase = 1;
+ Vashj = NULL;
}
void Aggro(Unit *who) { return; }
- void MoveInLineOfSight(Unit *who) { return; }
-
+ void MoveInLineOfSight(Unit *who){return;}
+
void UpdateAI(const uint32 diff)
{
- //Check_Timer
- if(Check_Timer < diff)
+ if(!pInstance)
+ return;
+
+ if (!Vashj){ Vashj = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_LADYVASHJ)); }
+
+ for (int i = 0;i<8;i++)//search for nearest waypoint (up on stairs)
+ {
+ if (!x || !y || !z)
+ {
+ x = ElementWPPos[i][0];
+ y = ElementWPPos[i][1];
+ z = ElementWPPos[i][2];
+ }
+ else
+ {
+ if (m_creature->GetDistance(ElementWPPos[i][0],ElementWPPos[i][1],ElementWPPos[i][2]) < m_creature->GetDistance(x,y,z))
+ {
+ x = ElementWPPos[i][0];
+ y = ElementWPPos[i][1];
+ z = ElementWPPos[i][2];
+ }
+ }
+ }
+
+ if (!Vashj)
+ {
+ m_creature->Say("Error Vashj not found!", LANG_UNIVERSAL, NULL);
+ return;
+ }
+
+ if(move < diff)
{
- if(pInstance)
+ if (phase == 1)
+ {
+ m_creature->GetMotionMaster()->MovePoint(0, x, y, z);
+ }
+ if (phase == 1 && m_creature->GetDistance(x,y,z) < 0.1)
+ {
+ phase = 2;
+ }
+ if (phase == 2)
+ {
+ m_creature->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z);
+ phase = 3;
+ }
+ if (phase == 3)
{
- Unit *Vashj = NULL;
- Vashj = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_LADYVASHJ));
- if(Vashj)
+ m_creature->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z);
+ if(m_creature->GetDistance(MIDDLE_X, MIDDLE_Y, MIDDLE_Z) < 3)
{
- if(Vashj->IsWithinDistInMap(m_creature, 5))
+ SpellEntry *spell = (SpellEntry *)GetSpellStore()->LookupEntry(SPELL_SURGE);
+ if( spell )
{
- //increase lady vashj damage (+5%)
- const CreatureInfo *cinfo = m_creature->GetCreatureInfo();
- Vashj->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 5)));
- Vashj->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 5)));
- m_creature->UpdateDamagePhysical(BASE_ATTACK);
-
- //call Unsummon()
- m_creature->setDeathState(JUST_DIED);
- }
- else if(((boss_lady_vashjAI*)((Creature*)Vashj)->AI())->InCombat == false)
- {
- //call Unsummon()
- m_creature->setDeathState(JUST_DIED);
+ for(uint32 i = 0;i<3;i++)
+ {
+ if (!spell->Effect[i])
+ continue;
+
+ Vashj->AddAura(new VashjSurgeAura(spell, i, NULL, Vashj, Vashj));
+ }
}
+ m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
}
}
- else error_log("ERROR: Instance Data for Serpentshrine Caverns not set");
- Check_Timer = 1000;
- }else Check_Timer -= diff;
+ if(((boss_lady_vashjAI*)((Creature*)Vashj)->AI())->InCombat == false || ((boss_lady_vashjAI*)((Creature*)Vashj)->AI())->Phase != 2 || Vashj->isDead())
+ {
+ //call Unsummon()
+ m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+ move = 1000;
+ }else move -= diff;
}
};
@@ -617,17 +690,19 @@ struct TRINITY_DLL_DECL mob_tainted_elementalAI : public ScriptedAI
{
mob_tainted_elementalAI(Creature *c) : ScriptedAI(c)
{
- pInstance = ((ScriptedInstance*)c->GetInstanceData());
+ pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL;
Reset();
}
ScriptedInstance *pInstance;
uint32 PoisonBolt_Timer;
+ uint32 Despawn_Timer;
void Reset()
{
PoisonBolt_Timer = 5000+rand()%5000;
+ Despawn_Timer = 30000;
}
void JustDied(Unit *killer)
@@ -644,6 +719,7 @@ struct TRINITY_DLL_DECL mob_tainted_elementalAI : public ScriptedAI
void Aggro(Unit *who)
{
+ m_creature->AddThreat(who, 0.1f);
}
void UpdateAI(const uint32 diff)
@@ -659,6 +735,16 @@ struct TRINITY_DLL_DECL mob_tainted_elementalAI : public ScriptedAI
PoisonBolt_Timer = 5000+rand()%5000;
}else PoisonBolt_Timer -= diff;
+
+ //Despawn_Timer
+ if(Despawn_Timer < diff)
+ {
+ //call Unsummon()
+ m_creature->setDeathState(DEAD);
+
+ //to prevent crashes
+ Despawn_Timer = 1000;
+ }else Despawn_Timer -= diff;
}
};
@@ -668,43 +754,77 @@ struct TRINITY_DLL_DECL mob_toxic_sporebatAI : public ScriptedAI
{
mob_toxic_sporebatAI(Creature *c) : ScriptedAI(c)
{
- pInstance = ((ScriptedInstance*)c->GetInstanceData());
- Reset();
+ pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL;
+ EnterEvadeMode();
}
ScriptedInstance *pInstance;
+ uint32 movement_timer;
uint32 ToxicSpore_Timer;
+ uint32 bolt_timer;
uint32 Check_Timer;
void Reset()
{
- m_creature->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING + MOVEMENTFLAG_ONTRANSPORT);
- m_creature->setFaction(14);
+ m_creature->AddUnitMovementFlag(/*MOVEMENTFLAG_ONTRANSPORT + */MOVEMENTFLAG_LEVITATING);
+ m_creature->setFaction(14);
+ movement_timer = 0;
ToxicSpore_Timer = 5000;
+ bolt_timer = 5500;
Check_Timer = 1000;
}
- void Aggro(Unit *who) {}
+ void Aggro(Unit *who)
+ {
+
+ }
+
+ void MoveInLineOfSight(Unit *who)
+ {
+
+ }
- void UpdateAI (const uint32 diff)
+ void MovementInform(uint32 type, uint32 id)
{
- //Return since we have no target
- if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() )
+ if(type != POINT_MOTION_TYPE)
return;
- //ToxicSpore_Timer
- if(ToxicSpore_Timer < diff)
- {
- Unit *target = NULL;
- target = SelectUnit(SELECT_TARGET_RANDOM, 0);
+ if(id == 1)
+ movement_timer = 0;
+ }
- //The Spores will hit you anywhere in the instance: underwater, at the elevator, at the entrance, wherever.
- if(target)
- DoCast(target, SPELL_TOXIC_SPORES);
+ void UpdateAI (const uint32 diff)
+ {
- ToxicSpore_Timer = 20000+rand()%5000;
- }else ToxicSpore_Timer -= diff;
+ /*if(!m_creature->isInCombat())
+ m_creature->SetInCombatState(false);*/
+
+ //Random movement
+ if (movement_timer < diff)
+ {
+ uint32 rndpos = rand()%8;
+ m_creature->GetMotionMaster()->MovePoint(1,SporebatWPPos[rndpos][0], SporebatWPPos[rndpos][1], SporebatWPPos[rndpos][2]);
+ movement_timer = 6000;
+ }else movement_timer -= diff;
+
+ //toxic spores
+ if(bolt_timer < diff)
+ {
+ Unit *target = NULL;
+ target = SelectUnit(SELECT_TARGET_RANDOM, 0);
+ if(target)
+ {
+ Creature* trig = m_creature->SummonCreature(TOXIC_SPORES_TRIGGER,target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,30000);
+ if(trig)
+ {
+ trig->setFaction(14);
+ trig->CastSpell(trig, SPELL_TOXIC_SPORES,true);
+ }
+ }
+ bolt_timer = 10000+rand()%5000;
+ }
+ else bolt_timer -= diff;
//Check_Timer
if(Check_Timer < diff)
@@ -714,7 +834,7 @@ struct TRINITY_DLL_DECL mob_toxic_sporebatAI : public ScriptedAI
//check if vashj is death
Unit *Vashj = NULL;
Vashj = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_LADYVASHJ));
- if(!Vashj || (Vashj && !Vashj->isAlive()))
+ if(!Vashj || (Vashj && !Vashj->isAlive()) || (Vashj && ((boss_lady_vashjAI*)((Creature*)Vashj)->AI())->Phase != 3))
{
//remove
m_creature->setDeathState(DEAD);
@@ -725,9 +845,7 @@ struct TRINITY_DLL_DECL mob_toxic_sporebatAI : public ScriptedAI
Check_Timer = 1000;
}else Check_Timer -= diff;
-
- DoMeleeAttackIfReady();
- }
+ }
};
//Coilfang Elite
@@ -748,7 +866,7 @@ CreatureAI* GetAI_mob_coilfang_elite(Creature *_Creature)
return ai;
}
-//Coilfang Strifer
+//Coilfang Strider
//It hits plate for about 8000 damage, has a Mind Blast spell doing about 3000 shadow damage, and a Psychic Scream Aura, which fears everybody in a 8 yard range of it every 2-3 seconds , for 5 seconds and increasing their movement speed by 150% during the fear.
CreatureAI* GetAI_mob_coilfang_strider(Creature *_Creature)
{
@@ -772,21 +890,19 @@ struct TRINITY_DLL_DECL mob_shield_generator_channelAI : public ScriptedAI
{
mob_shield_generator_channelAI(Creature *c) : ScriptedAI(c)
{
- pInstance = ((ScriptedInstance*)c->GetInstanceData());
+ pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL;
Reset();
}
ScriptedInstance *pInstance;
-
uint32 Check_Timer;
- bool Channeled;
-
+ bool Casted;
void Reset()
{
- Check_Timer = 1000;
- Channeled = false;
- //invisible
- m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID , 11686);
+ Check_Timer = 0;
+ Casted = false;
+ m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID , 11686); //invisible
+
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
@@ -799,7 +915,7 @@ struct TRINITY_DLL_DECL mob_shield_generator_channelAI : public ScriptedAI
if(!pInstance)
return;
- if(!Channeled)
+ if(Check_Timer < diff)
{
Unit *Vashj = NULL;
Vashj = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_LADYVASHJ));
@@ -807,22 +923,24 @@ struct TRINITY_DLL_DECL mob_shield_generator_channelAI : public ScriptedAI
if(Vashj && Vashj->isAlive())
{
//start visual channel
- m_creature->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, Vashj->GetGUID());
- m_creature->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_MAGIC_BARRIER);
- Channeled = true;
+ if (!Casted || !Vashj->HasAura(SPELL_MAGIC_BARRIER,0))
+ {
+ m_creature->CastSpell(Vashj,SPELL_MAGIC_BARRIER,true);
+ Casted = true;
+ }
}
- }
+ Check_Timer = 1000;
+ }else Check_Timer -= diff;
}
};
bool ItemUse_item_tainted_core(Player *player, Item* _Item, SpellCastTargets const& targets)
{
- ScriptedInstance *pInstance = ((ScriptedInstance*)player->GetInstanceData());
+ ScriptedInstance *pInstance = (player->GetInstanceData()) ? ((ScriptedInstance*)player->GetInstanceData()) : NULL;
if(!pInstance)
{
- player->GetSession()->SendNotification("ERROR: Instance script not initialized. Notify your administrator.");
- error_log("ERROR: Lady Vashj Tainted Core: Instance Script Not Initialized");
+ player->GetSession()->SendNotification("Instance script not initialized");
return true;
}
@@ -854,7 +972,6 @@ bool ItemUse_item_tainted_core(Player *player, Item* _Item, SpellCastTargets con
break;
default:
return true;
- break;
}
if(pInstance->GetData(identifier))
@@ -869,7 +986,7 @@ bool ItemUse_item_tainted_core(Player *player, Item* _Item, SpellCastTargets con
if(Channel)
{
//call Unsummon()
- Channel->setDeathState(JUST_DIED);
+ Channel->setDeathState(JUST_DIED);
}
pInstance->SetData(identifier, 1);
@@ -949,3 +1066,5 @@ void AddSC_boss_lady_vashj()
newscript->pItemUse = ItemUse_item_tainted_core;
m_scripts[nrscripts++] = newscript;
}
+
+
diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp
index e3ec3527d05..7b2bc68198e 100644
--- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp
+++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp
@@ -16,14 +16,42 @@
/* ScriptData
SDName: Boss_Leotheras_The_Blind
-SD%Complete: 50
-SDComment: Missing Inner Demons
+SD%Complete: 80
+SDComment: Possesion Support
SDCategory: Coilfang Resevoir, Serpent Shrine Cavern
EndScriptData */
#include "precompiled.h"
#include "def_serpent_shrine.h"
+// --- Spells used by Leotheras The Blind
+#define SPELL_WHIRLWIND 37640
+#define SPELL_CHAOS_BLAST 37674
+#define SPELL_BERSERK 26662
+#define SPELL_INSIDIOUS_WHISPER 37676
+#define SPELL_DUAL_WIELD 42459
+
+// --- Spells used in banish phase ---
+#define BANISH_BEAM 38909
+#define AURA_BANISH 37833
+
+// --- Spells used by Greyheart Spellbinders
+#define SPELL_EARTHSHOCK 39076
+#define SPELL_MINDBLAST 37531
+
+// --- Spells used by Inner Demons and creature ID
+#define INNER_DEMON_ID 21857
+#define AURA_DEMONIC_ALIGNMENT 37713
+#define SPELL_SHADOWBOLT 39309
+#define SPELL_SOUL_LINK 38007
+#define SPELL_CONSUMING_MADNESS 37749 //not supported by core yet
+
+//Misc.
+#define MODEL_DEMON 20125
+#define MODEL_NIGHTELF 20514
+#define DEMON_FORM 21875
+#define MOB_SPELLBINDER 21806
+
#define SAY_AGGRO -1548009
#define SAY_SWITCH_TO_DEMON -1548010
#define SAY_INNER_DEMONS -1548011
@@ -37,59 +65,297 @@ EndScriptData */
#define SAY_FREE -1548019
#define SAY_DEATH -1548020
-#define SPELL_WHIRLWIND 40653
-#define SPELL_CHAOS_BLAST 37675
-//#define SPELL_INSIDIOUS_WHISPER 37676 // useless - dummy effect that can't be implemented
+class TRINITY_DLL_DECL InsidiousAura : public Aura {
+public:
+ InsidiousAura(SpellEntry *spell, uint32 eff, int32 *bp, Unit *target, Unit *caster) : Aura(spell, eff, bp, target, caster, NULL)
+ {}
+};
-#define MODEL_DEMON 14555
-#define MODEL_NIGHTELF 20514
+struct TRINITY_DLL_DECL mob_inner_demonAI : public ScriptedAI
+{
+ mob_inner_demonAI(Creature *c) : ScriptedAI(c)
+ {
+ victimGUID = 0;
+ Reset();
+ }
+
+ uint32 ShadowBolt_Timer;
+
+ uint32 Link_Timer;
+ uint64 victimGUID;
+
+ void Reset()
+ {
+ ShadowBolt_Timer = 10000;
+ Link_Timer = 1000;
+ }
+ void JustDied(Unit *victim)
+ {
+ Unit* pUnit = Unit::GetUnit((*m_creature),victimGUID);
+ if (pUnit && pUnit->HasAura(SPELL_INSIDIOUS_WHISPER,0))
+ pUnit->RemoveAurasDueToSpell(SPELL_INSIDIOUS_WHISPER);
+ }
+
+ void DamageTaken(Unit *done_by, uint32 &damage)
+ {
+ if(done_by->GetGUID() != victimGUID && done_by->GetGUID() != m_creature->GetGUID())
+ {
+ damage = 0;
+ m_creature->getThreatManager().modifyThreatPercent(done_by, -100);
+ }
+ }
+
+ void Aggro(Unit *who)
+ {
+ if (!victimGUID) return;
+ }
-#define DEMON_FORM 21845
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostilTarget() || !m_creature->getVictim())
+ return;
+ if (m_creature->getVictim()->GetGUID() != victimGUID)
+ {
+ Unit* owner = Unit::GetUnit((*m_creature),victimGUID);
+ if (owner)
+ AttackStart(owner);
+ }
+ if(Link_Timer < diff)
+ {
+ DoCast(m_creature->getVictim(), SPELL_SOUL_LINK, true);
+ Link_Timer = 1000;
+ }else Link_Timer -= diff;
+
+
+ if(!m_creature->HasAura(AURA_DEMONIC_ALIGNMENT, 0))
+ DoCast(m_creature, AURA_DEMONIC_ALIGNMENT,true);
+
+ if(ShadowBolt_Timer < diff)
+ {
+ DoCast(m_creature->getVictim(), SPELL_SHADOWBOLT, false);
+ ShadowBolt_Timer = 10000;
+ }else ShadowBolt_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
//Original Leotheras the Blind AI
struct TRINITY_DLL_DECL boss_leotheras_the_blindAI : public ScriptedAI
{
boss_leotheras_the_blindAI(Creature *c) : ScriptedAI(c)
{
- pInstance = ((ScriptedInstance*)c->GetInstanceData());
+ m_creature->GetPosition(x,y,z);
+ pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL;
Demon = 0;
+
+ for(uint8 i = 0; i < 3; i++)//clear guids
+ SpellBinderGUID[i] = 0;
Reset();
- }
+ }
ScriptedInstance *pInstance;
uint32 Whirlwind_Timer;
uint32 ChaosBlast_Timer;
- uint32 Switch_Timer;
-
+ uint32 SwitchToDemon_Timer;
+ uint32 SwitchToHuman_Timer;
+ uint32 Berserk_Timer;
+ uint32 InnerDemons_Timer;
+ uint32 BanishTimer;
+
+ bool DealDamage;
+ bool NeedThreatReset;
bool DemonForm;
bool IsFinalForm;
-
+ bool EnrageUsed;
+ float x,y,z;
+
+ uint64 InnderDemon[5];
+ uint32 InnderDemon_Count;
uint64 Demon;
+ uint64 SpellBinderGUID[3];
void Reset()
{
- Whirlwind_Timer = 20000;
+ CheckChannelers();
+ BanishTimer = 1000;
+ Whirlwind_Timer = 15000;
ChaosBlast_Timer = 1000;
- Switch_Timer = 45000;
-
+ SwitchToDemon_Timer = 45000;
+ SwitchToHuman_Timer = 60000;
+ Berserk_Timer = 600000;
+ InnerDemons_Timer = 30000;
+ m_creature->SetCanDualWield(true);
+ DealDamage = true;
DemonForm = false;
IsFinalForm = false;
-
- m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF);
-
- if (pInstance)
- pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, NOT_STARTED);
+ NeedThreatReset = false;
+ EnrageUsed = false;
+ InnderDemon_Count = 0;
+ m_creature->SetSpeed( MOVE_RUN, 2.0f, true);
+ m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
+ m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true);
+ m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF);
+ m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY , 0);
+ m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0);
+ m_creature->CastSpell(m_creature, SPELL_DUAL_WIELD, true);
+ m_creature->SetCorpseDelay(1000*60*60);
+ if(pInstance)
+ pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, NOT_STARTED);
}
+ void CheckChannelers(bool DoEvade = true)
+ {
+ for(uint8 i = 0; i < 3; i++)
+ {
+ Creature *add = (Creature*)Unit::GetUnit(*m_creature,SpellBinderGUID[i]);
+ if (add && add->isAlive())
+ {
+ add->setDeathState(DEAD);
+ add->RemoveCorpse();
+ }else{
+ if(add && add->isDead())
+ add->RemoveCorpse();
+ }
+ float nx = x;
+ float ny = y;
+ float o = 2.4f;
+ if (i == 0) {nx += 20;o=3.0f;}
+ if (i == 1) ny -= 20;
+ if (i == 2) {nx += 18;ny -= 18;o=2.0f;}
+ Creature* binder = m_creature->SummonCreature(MOB_SPELLBINDER,nx,ny,z,o,TEMPSUMMON_DEAD_DESPAWN,0);
+ if (binder)
+ SpellBinderGUID[i] = binder->GetGUID();
+
+ }
+ }
+ void MoveInLineOfSight(Unit *who)
+ {
+ if(m_creature->HasAura(AURA_BANISH, 0))
+ return;
+
+ if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) )
+ {
+ if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
+ return;
+
+ float attackRadius = m_creature->GetAttackDistance(who);
+ if(m_creature->IsWithinDistInMap(who, attackRadius))
+ {
+ // Check first that object is in an angle in front of this one before LoS check
+ if( m_creature->HasInArc(M_PI/2.0f, who) && m_creature->IsWithinLOSInMap(who) )
+ {
+ AttackStart(who);
+ who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
+ if (!InCombat)
+ {
+ Aggro(who);
+ InCombat = true;
+ }
+ }
+ }
+ }
+ }
+
void StartEvent()
{
DoScriptText(SAY_AGGRO, m_creature);
-
- if (pInstance)
+ if(pInstance)
pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, IN_PROGRESS);
}
+ void CheckBanish()
+ {
+ uint8 AliveChannelers = 0;
+ for(uint8 i = 0; i < 3; i++)
+ {
+ Unit *add = Unit::GetUnit(*m_creature,SpellBinderGUID[i]);
+ if (add && add->isAlive())
+ AliveChannelers++;
+ }
+
+ // channelers == 0 remove banish aura
+ if(AliveChannelers == 0 && m_creature->HasAura(AURA_BANISH, 0))
+ {
+ // removing banish aura
+ m_creature->RemoveAurasDueToSpell(AURA_BANISH);
+
+ // Leotheras is getting immune again
+ m_creature->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, true);
+
+ // changing model to bloodelf
+ m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF);
+
+ // and reseting equipment
+ m_creature->LoadEquipment(m_creature->GetEquipmentId());
+
+ if(pInstance && pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER))
+ {
+ Unit *victim = NULL;
+ victim = Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER));
+ if(victim)
+ m_creature->getThreatManager().addThreat(victim, 1);
+ StartEvent();
+ }
+ }
+ else if(AliveChannelers != 0 && !m_creature->HasAura(AURA_BANISH, 0))
+ {
+ // channelers != 0 apply banish aura
+ // removing Leotheras banish immune to apply AURA_BANISH
+ m_creature->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, false);
+ DoCast(m_creature, AURA_BANISH);
+
+ // changing model
+ m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_DEMON);
+
+ // and removing weapons
+ m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY , 0);
+ m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0);
+ }
+ }
+
+ //Despawn all Inner Demon summoned
+ void DespawnDemon()
+ {
+ for(int i=0; i<5; i++)
+ {
+ if(InnderDemon[i])
+ {
+ //delete creature
+ Unit* pUnit = Unit::GetUnit((*m_creature), InnderDemon[i]);
+ if (pUnit && pUnit->isAlive())
+ {
+ pUnit->DealDamage(pUnit, pUnit->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+ InnderDemon[i] = 0;
+ }
+ }
+
+ InnderDemon_Count = 0;
+ }
+
+ void CastConsumingMadness() //remove this once SPELL_INSIDIOUS_WHISPER is supported by core
+ {
+ for(int i=0; i<5; i++)
+ {
+ if(InnderDemon[i] > 0 )
+ {
+ Unit* pUnit = Unit::GetUnit((*m_creature), InnderDemon[i]);
+ if (pUnit && pUnit->isAlive())
+ {
+ Unit* pUnit_target = Unit::GetUnit((*pUnit), ((mob_inner_demonAI *)((Creature *)pUnit)->AI())->victimGUID);
+ if( pUnit_target && pUnit_target->isAlive())
+ {
+ pUnit->CastSpell(pUnit_target, SPELL_CONSUMING_MADNESS, true);
+ m_creature->getThreatManager().modifyThreatPercent(pUnit_target, -100);
+ }
+ }
+ }
+ }
+ }
+
void KilledUnit(Unit *victim)
{
if (victim->GetTypeId() != TYPEID_PLAYER)
@@ -128,84 +394,191 @@ struct TRINITY_DLL_DECL boss_leotheras_the_blindAI : public ScriptedAI
if (pUnit)
pUnit->DealDamage(pUnit, pUnit->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
}
-
if (pInstance)
pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, DONE);
}
void Aggro(Unit *who)
{
- StartEvent();
+ if(m_creature->HasAura(AURA_BANISH, 0))
+ return;
+
+ m_creature->LoadEquipment(m_creature->GetEquipmentId());
}
void UpdateAI(const uint32 diff)
{
//Return since we have no target
- if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() )
- return;
-
- if (!DemonForm)
+ if (m_creature->HasAura(AURA_BANISH, 0) || !m_creature->SelectHostilTarget() || !m_creature->getVictim())
+ {
+ if(BanishTimer<diff)
+ {
+ CheckBanish();//no need to check every update tick
+ BanishTimer = 1000;
+ }else BanishTimer -= diff;
+ return;
+ }
+ if(m_creature->HasAura(SPELL_WHIRLWIND, 0))
+ if(Whirlwind_Timer < diff)
+ {
+ Unit *newTarget = SelectUnit(SELECT_TARGET_RANDOM, 0);
+ if(newTarget)
+ {
+ DoResetThreat();
+ m_creature->GetMotionMaster()->Clear();
+ m_creature->GetMotionMaster()->MovePoint(0,newTarget->GetPositionX(),newTarget->GetPositionY(),newTarget->GetPositionZ());
+ }
+ Whirlwind_Timer = 2000;
+ }else Whirlwind_Timer -= diff;
+
+ // reseting after changing forms and after ending whirlwind
+ if(NeedThreatReset && !m_creature->HasAura(SPELL_WHIRLWIND, 0))
+ {
+ // when changing forms seting timers (or when ending whirlwind - to avoid adding new variable i use Whirlwind_Timer to countdown 2s while whirlwinding)
+ if(DemonForm)
+ InnerDemons_Timer = 30000;
+ else
+ Whirlwind_Timer = 15000;
+
+ NeedThreatReset = false;
+ DoResetThreat();
+ m_creature->GetMotionMaster()->Clear();
+ m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
+ }
+
+ //Enrage_Timer ( 10 min )
+ if(Berserk_Timer < diff && !EnrageUsed)
{
- //Whirlwind_Timer
- if (Whirlwind_Timer < diff)
- {
- DoCast(m_creature, SPELL_WHIRLWIND);
- Whirlwind_Timer = 25000;
- }else Whirlwind_Timer -= diff;
+ DoCast(m_creature, SPELL_BERSERK);
+ EnrageUsed = true;
+ }else Berserk_Timer -= diff;
+ if(!DemonForm)
+ {
+ //Whirldind Timer
+ if(!m_creature->HasAura(SPELL_WHIRLWIND, 0))
+ {
+ if(Whirlwind_Timer < diff)
+ {
+ DoCast(m_creature, SPELL_WHIRLWIND);
+ // while whirlwinding this variable is used to countdown target's change
+ Whirlwind_Timer = 2000;
+ NeedThreatReset = true;
+ }else Whirlwind_Timer -= diff;
+ }
//Switch_Timer
- if (!IsFinalForm)
- {
- if (Switch_Timer < diff)
+
+ if(!IsFinalForm)
+ if(SwitchToDemon_Timer < diff)
{
//switch to demon form
- m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_DEMON);
- DoScriptText(SAY_SWITCH_TO_DEMON, m_creature);
- DemonForm = true;
- Switch_Timer = 60000;
- }else Switch_Timer -= diff;
- }
-
+ m_creature->RemoveAurasDueToSpell(SPELL_WHIRLWIND,0);
+ m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_DEMON);
+ DoScriptText(SAY_SWITCH_TO_DEMON, m_creature);
+ m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY , 0);
+ m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0);
+ DemonForm = true;
+ NeedThreatReset = true;
+ SwitchToDemon_Timer = 45000;
+ }else SwitchToDemon_Timer -= diff;
DoMeleeAttackIfReady();
}
else
{
//ChaosBlast_Timer
- if (ChaosBlast_Timer < diff)
- {
- DoCast(m_creature->getVictim(), SPELL_CHAOS_BLAST);
- ChaosBlast_Timer = 1500;
- }else ChaosBlast_Timer -= diff;
+ if (!m_creature->getVictim())
+ return;
+ if(m_creature->GetDistance(m_creature->getVictim()) < 30)
+ m_creature->StopMoving();
+ if(ChaosBlast_Timer < diff)
+ {
+ // will cast only when in range of spell
+ if(m_creature->GetDistance(m_creature->getVictim()) < 30)
+ {
+ //m_creature->CastSpell(m_creature->getVictim(), SPELL_CHAOS_BLAST, true);
+ int damage = 100;
+ m_creature->CastCustomSpell(m_creature->getVictim(), SPELL_CHAOS_BLAST, &damage, NULL, NULL, false, NULL, NULL, m_creature->GetGUID());
+ }
+ ChaosBlast_Timer = 3000;
+ }else ChaosBlast_Timer -= diff;
+ //Summon Inner Demon
+ if(InnerDemons_Timer < diff)
+ {
+ std::list<HostilReference *>& ThreatList = m_creature->getThreatManager().getThreatList();
+ std::vector<Unit *> TargetList;
+ for(std::list<HostilReference *>::iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr)
+ {
+ Unit *tempTarget = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());
+ if(tempTarget && tempTarget->GetTypeId() == TYPEID_PLAYER && tempTarget->GetGUID() != m_creature->getVictim()->GetGUID() && TargetList.size()<5)
+ TargetList.push_back( tempTarget );
+ }
+ SpellEntry *spell = (SpellEntry *)GetSpellStore()->LookupEntry(SPELL_INSIDIOUS_WHISPER);
+ for(std::vector<Unit *>::iterator itr = TargetList.begin(); itr != TargetList.end(); ++itr)
+ {
+ if( (*itr) && (*itr)->isAlive() )
+ {
+ Creature * demon = (Creature *)m_creature->SummonCreature(INNER_DEMON_ID, (*itr)->GetPositionX()+10, (*itr)->GetPositionY()+10, (*itr)->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ if(demon)
+ {
+ ((ScriptedAI *)demon->AI())->AttackStart( (*itr) );
+ ((mob_inner_demonAI *)demon->AI())->victimGUID = (*itr)->GetGUID();
+
+ for (int i=0; i<3; i++)
+ {
+ if (!spell->Effect[i])
+ continue;
+ (*itr)->AddAura(new InsidiousAura(spell, i, NULL, (*itr), (*itr)));
+ }
+ if( InnderDemon_Count > 4 ) InnderDemon_Count = 0;
+
+ //Safe storing of creatures
+ InnderDemon[InnderDemon_Count] = demon->GetGUID();
+
+ //Update demon count
+ InnderDemon_Count++;
+ }
+ }
+ }
+ DoScriptText(SAY_INNER_DEMONS, m_creature);
+
+ InnerDemons_Timer = 999999;
+ }else InnerDemons_Timer -= diff;
//Switch_Timer
- if (Switch_Timer < diff)
+ if(SwitchToHuman_Timer < diff)
{
//switch to nightelf form
m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF);
+ m_creature->LoadEquipment(m_creature->GetEquipmentId());
+
+ CastConsumingMadness();
+ DespawnDemon();
+
DemonForm = false;
+ NeedThreatReset = true;
- Switch_Timer = 45000;
- }else Switch_Timer -= diff;
- }
+ SwitchToHuman_Timer = 60000;
+ }else SwitchToHuman_Timer -= diff;
+ }
if (!IsFinalForm && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 15)
{
//at this point he divides himself in two parts
- Creature *Copy = NULL;
- Copy = DoSpawnCreature(DEMON_FORM, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
-
- if (Copy)
- {
- Demon = Copy->GetGUID();
- Copy->AI()->AttackStart(m_creature->getVictim());
- }
-
+ Creature *Copy = NULL;
+ Copy = DoSpawnCreature(DEMON_FORM, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 6000);
+ if(Copy)
+ {
+ Demon = Copy->GetGUID();
+ if (m_creature->getVictim())
+ Copy->AI()->AttackStart(m_creature->getVictim());
+ }
//set nightelf final form
IsFinalForm = true;
DemonForm = false;
DoScriptText(SAY_FINAL_FORM, m_creature);
- m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF);
+ m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF);
+ m_creature->LoadEquipment(m_creature->GetEquipmentId());
}
}
};
@@ -219,10 +592,12 @@ struct TRINITY_DLL_DECL boss_leotheras_the_blind_demonformAI : public ScriptedAI
}
uint32 ChaosBlast_Timer;
+ bool DealDamage;
void Reset()
{
ChaosBlast_Timer = 1000;
+ DealDamage = true;
}
void StartEvent()
@@ -259,18 +634,147 @@ struct TRINITY_DLL_DECL boss_leotheras_the_blind_demonformAI : public ScriptedAI
//Return since we have no target
if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() )
return;
-
//ChaosBlast_Timer
- if (ChaosBlast_Timer < diff)
- {
- DoCast(m_creature->getVictim(), SPELL_CHAOS_BLAST);
- ChaosBlast_Timer = 1500;
- }else ChaosBlast_Timer -= diff;
+ if(m_creature->GetDistance(m_creature->getVictim()) < 30)
+ m_creature->StopMoving();
+
+ if(ChaosBlast_Timer < diff)
+ {
+ // will cast only when in range od spell
+ if(m_creature->GetDistance(m_creature->getVictim()) < 30)
+ {
+ //m_creature->CastSpell(m_creature->getVictim(),SPELL_CHAOS_BLAST,true);
+ int damage = 100;
+ m_creature->CastCustomSpell(m_creature->getVictim(), SPELL_CHAOS_BLAST, &damage, NULL, NULL, false, NULL, NULL, m_creature->GetGUID());
+ ChaosBlast_Timer = 3000;
+ }
+ }else ChaosBlast_Timer -= diff;
//Do NOT deal any melee damage to the target.
}
};
-
+struct TRINITY_DLL_DECL mob_greyheart_spellbinderAI : public ScriptedAI
+{
+ mob_greyheart_spellbinderAI(Creature *c) : ScriptedAI(c)
+ {
+ pInstance = ((ScriptedInstance *)c->GetInstanceData());;
+ leotherasGUID = 0;
+ AddedBanish = false;
+ Reset();
+ }
+
+ ScriptedInstance *pInstance;
+
+ uint64 leotherasGUID;
+
+ uint32 Mindblast_Timer;
+ uint32 Earthshock_Timer;
+
+ bool AddedBanish;
+
+ void Reset()
+ {
+ Mindblast_Timer = 3000 + rand()%5000;
+ Earthshock_Timer = 5000 + rand()%5000;
+
+ if(pInstance)
+ {
+ pInstance->SetData64(DATA_LEOTHERAS_EVENT_STARTER, 0);
+ Creature *leotheras = (Creature *)Unit::GetUnit(*m_creature, leotherasGUID);
+ if(leotheras && leotheras->isAlive())
+ ((boss_leotheras_the_blindAI*)leotheras->AI())->CheckChannelers(false);
+ }
+ }
+
+ void Aggro(Unit *who)
+ {
+ m_creature->InterruptNonMeleeSpells(false);
+ if(pInstance)
+ pInstance->SetData64(DATA_LEOTHERAS_EVENT_STARTER, who->GetGUID());
+ }
+
+ void JustRespawned()
+ {
+ InCombat = false;
+ AddedBanish = false;
+ Reset();
+ }
+
+ void CastChanneling()
+ {
+ if(!InCombat && !m_creature->m_currentSpells[CURRENT_CHANNELED_SPELL])
+ {
+ if(leotherasGUID)
+ {
+ Creature *leotheras = (Creature *)Unit::GetUnit(*m_creature, leotherasGUID);
+ if(leotheras && leotheras->isAlive())
+ DoCast(leotheras, BANISH_BEAM);
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if(pInstance)
+ {
+ if(!leotherasGUID)
+ leotherasGUID = pInstance->GetData64(DATA_LEOTHERAS);
+
+ if(!InCombat && pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER))
+ {
+ Unit *victim = NULL;
+ victim = Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER));
+ if(victim)
+ AttackStart(victim);
+ }
+ }
+
+ if(!m_creature->SelectHostilTarget() || !m_creature->getVictim())
+ {
+ CastChanneling();
+ return;
+ }
+
+ if(pInstance && !pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER))
+ {
+ EnterEvadeMode();
+ return;
+ }
+
+ if(Mindblast_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = SelectUnit(SELECT_TARGET_RANDOM,0);
+
+ if ( target )DoCast(target, SPELL_MINDBLAST);
+
+ Mindblast_Timer = 10000 + rand()%5000;
+ }else Mindblast_Timer -= diff;
+
+ if(Earthshock_Timer < diff)
+ {
+ Map *map = m_creature->GetMap();
+ InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers();
+ for(InstanceMap::PlayerList::const_iterator itr = PlayerList.begin();itr != PlayerList.end(); ++itr)
+ {
+ bool isCasting = false;
+ for(uint8 i = 0; i < CURRENT_MAX_SPELL; ++i)
+ if((*itr)->m_currentSpells[i])
+ isCasting = true;
+
+ if(isCasting)
+ {
+ DoCast((*itr), SPELL_EARTHSHOCK);
+ break;
+ }
+ }
+ Earthshock_Timer = 8000 + rand()%7000;
+ }else Earthshock_Timer -= diff;
+ DoMeleeAttackIfReady();
+ }
+
+ void JustDied(Unit *killer) {}
+};
CreatureAI* GetAI_boss_leotheras_the_blind(Creature *_Creature)
{
return new boss_leotheras_the_blindAI (_Creature);
@@ -281,6 +785,15 @@ CreatureAI* GetAI_boss_leotheras_the_blind_demonform(Creature *_Creature)
return new boss_leotheras_the_blind_demonformAI (_Creature);
}
+CreatureAI* GetAI_mob_greyheart_spellbinder(Creature *_Creature)
+{
+ return new mob_greyheart_spellbinderAI (_Creature);
+}
+
+CreatureAI* GetAI_mob_inner_demon(Creature *_Creature)
+{
+ return new mob_inner_demonAI (_Creature);
+}
void AddSC_boss_leotheras_the_blind()
{
Script *newscript;
@@ -294,4 +807,14 @@ void AddSC_boss_leotheras_the_blind()
newscript->Name="boss_leotheras_the_blind_demonform";
newscript->GetAI = GetAI_boss_leotheras_the_blind_demonform;
m_scripts[nrscripts++] = newscript;
+
+ newscript = new Script;
+ newscript->Name="mob_greyheart_spellbinder";
+ newscript->GetAI = GetAI_mob_greyheart_spellbinder;
+ m_scripts[nrscripts++] = newscript;
+
+ newscript = new Script;
+ newscript->Name="mob_inner_demon";
+ newscript->GetAI = GetAI_mob_inner_demon;
+ m_scripts[nrscripts++] = newscript;
}
diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/def_serpent_shrine.h b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/def_serpent_shrine.h
index 21d76d6854a..9d8cdad6849 100644
--- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/def_serpent_shrine.h
+++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/def_serpent_shrine.h
@@ -23,4 +23,6 @@
#define DATA_THELURKERBELOWEVENT 16
#define DATA_TIDALVESS 17
#define DATA_FATHOMLORDKARATHRESSEVENT 18
+#define DATA_LEOTHERAS 19
+#define DATA_LEOTHERAS_EVENT_STARTER 20
#endif
diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp
index cc4992a000a..d34c8910c2f 100644
--- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp
+++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp
@@ -16,8 +16,8 @@
/* ScriptData
SDName: Instance_Serpent_Shrine
-SD%Complete: 0
-SDComment: VERIFY SCRIPT
+SD%Complete: 100
+SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Serpent Shrine Scripts
SDCategory: Coilfang Resevoir, Serpent Shrine Cavern
EndScriptData */
@@ -46,6 +46,9 @@ struct TRINITY_DLL_DECL instance_serpentshrine_cavern : public ScriptedInstance
uint64 Karathress;
uint64 KarathressEvent_Starter;
+ uint64 LeotherasTheBlind;
+ uint64 LeotherasEventStarter;
+
bool ShieldGeneratorDeactivated[4];
bool Encounters[ENCOUNTERS];
@@ -59,6 +62,9 @@ struct TRINITY_DLL_DECL instance_serpentshrine_cavern : public ScriptedInstance
Karathress = 0;
KarathressEvent_Starter = 0;
+ LeotherasTheBlind = 0;
+ LeotherasEventStarter = 0;
+
ShieldGeneratorDeactivated[0] = false;
ShieldGeneratorDeactivated[1] = false;
ShieldGeneratorDeactivated[2] = false;
@@ -80,36 +86,34 @@ struct TRINITY_DLL_DECL instance_serpentshrine_cavern : public ScriptedInstance
{
switch(creature_entry)
{
- case 21212: LadyVashj = creature->GetGUID(); break;
- case 21214: Karathress = creature->GetGUID(); break;
- case 21966: Sharkkis = creature->GetGUID(); break;
- case 21965: Tidalvess = creature->GetGUID(); break;
- case 21964: Caribdis = creature->GetGUID(); break;
- }
+ case 21212: LadyVashj = creature->GetGUID(); break;
+ case 21214: Karathress = creature->GetGUID(); break;
+ case 21966: Sharkkis = creature->GetGUID(); break;
+ case 21965: Tidalvess = creature->GetGUID(); break;
+ case 21964: Caribdis = creature->GetGUID(); break;
+ case 21215: LeotherasTheBlind = creature->GetGUID(); break;}
}
void SetData64(uint32 type, uint64 data)
{
if(type == DATA_KARATHRESSEVENT_STARTER)
- KarathressEvent_Starter = data;
+ KarathressEvent_Starter = data;
+ if(type == DATA_LEOTHERAS_EVENT_STARTER)
+ LeotherasEventStarter = data;
}
uint64 GetData64(uint32 identifier)
{
switch(identifier)
{
- case DATA_SHARKKIS:
- return Sharkkis;
- case DATA_TIDALVESS:
- return Tidalvess;
- case DATA_CARIBDIS:
- return Caribdis;
- case DATA_LADYVASHJ:
- return LadyVashj;
- case DATA_KARATHRESS:
- return Karathress;
- case DATA_KARATHRESSEVENT_STARTER:
- return KarathressEvent_Starter;
+ case DATA_SHARKKIS: return Sharkkis;
+ case DATA_TIDALVESS: return Tidalvess;
+ case DATA_CARIBDIS: return Caribdis;
+ case DATA_LADYVASHJ: return LadyVashj;
+ case DATA_KARATHRESS: return Karathress;
+ case DATA_KARATHRESSEVENT_STARTER: return KarathressEvent_Starter;
+ case DATA_LEOTHERAS: return LeotherasTheBlind;
+ case DATA_LEOTHERAS_EVENT_STARTER: return LeotherasEventStarter;
}
return 0;
}
@@ -118,98 +122,82 @@ struct TRINITY_DLL_DECL instance_serpentshrine_cavern : public ScriptedInstance
{
switch(type)
{
- case DATA_HYDROSSTHEUNSTABLEEVENT:
- Encounters[0] = (data) ? true : false;
- break;
-
- case DATA_LEOTHERASTHEBLINDEVENT:
- Encounters[1] = (data) ? true : false;
- break;
-
- case DATA_THELURKERBELOWEVENT:
- Encounters[2] = (data) ? true : false;
- break;
-
- case DATA_KARATHRESSEVENT:
- Encounters[3] = (data) ? true : false;
- break;
-
- case DATA_MOROGRIMTIDEWALKEREVENT:
- Encounters[4] = (data) ? true : false;
- break;
+ case DATA_HYDROSSTHEUNSTABLEEVENT: Encounters[0] = data; break;
+ case DATA_LEOTHERASTHEBLINDEVENT: Encounters[1] = data; break;
+ case DATA_THELURKERBELOWEVENT: Encounters[2] = data; break;
+ case DATA_KARATHRESSEVENT: Encounters[3] = data; break;
+ case DATA_MOROGRIMTIDEWALKEREVENT: Encounters[4] = data; break;
//Lady Vashj
case DATA_LADYVASHJEVENT:
- if(data == 0)
+ if(data == NOT_STARTED)
{
ShieldGeneratorDeactivated[0] = false;
ShieldGeneratorDeactivated[1] = false;
ShieldGeneratorDeactivated[2] = false;
ShieldGeneratorDeactivated[3] = false;
}
- Encounters[5] = (data) ? true : false;
- break;
-
- case DATA_SHIELDGENERATOR1:
- ShieldGeneratorDeactivated[0] = (data) ? true : false;
- break;
-
- case DATA_SHIELDGENERATOR2:
- ShieldGeneratorDeactivated[1] = (data) ? true : false;
- break;
-
- case DATA_SHIELDGENERATOR3:
- ShieldGeneratorDeactivated[2] = (data) ? true : false;
- break;
-
- case DATA_SHIELDGENERATOR4:
- ShieldGeneratorDeactivated[3] = (data) ? true : false;
- break;
+ Encounters[5] = data; break;
+ case DATA_SHIELDGENERATOR1:ShieldGeneratorDeactivated[0] = (data) ? true : false; break;
+ case DATA_SHIELDGENERATOR2:ShieldGeneratorDeactivated[1] = (data) ? true : false; break;
+ case DATA_SHIELDGENERATOR3:ShieldGeneratorDeactivated[2] = (data) ? true : false; break;
+ case DATA_SHIELDGENERATOR4:ShieldGeneratorDeactivated[3] = (data) ? true : false; break;
}
+ if(data = DONE)
+ SaveToDB();
}
uint32 GetData(uint32 type)
{
switch(type)
{
- case DATA_HYDROSSTHEUNSTABLEEVENT:
- return Encounters[0];
-
- case DATA_LEOTHERASTHEBLINDEVENT:
- return Encounters[1];
-
- case DATA_THELURKERBELOWEVENT:
- return Encounters[2];
-
- case DATA_KARATHRESSEVENT:
- return Encounters[3];
-
- case DATA_MOROGRIMTIDEWALKEREVENT:
- return Encounters[4];
-
+ case DATA_HYDROSSTHEUNSTABLEEVENT: return Encounters[0];
+ case DATA_LEOTHERASTHEBLINDEVENT: return Encounters[1];
+ case DATA_THELURKERBELOWEVENT: return Encounters[2];
+ case DATA_KARATHRESSEVENT: return Encounters[3];
+ case DATA_MOROGRIMTIDEWALKEREVENT: return Encounters[4];
//Lady Vashj
- case DATA_LADYVASHJEVENT:
- return Encounters[5];
-
- case DATA_SHIELDGENERATOR1:
- return ShieldGeneratorDeactivated[0];
-
- case DATA_SHIELDGENERATOR2:
- return ShieldGeneratorDeactivated[1];
-
- case DATA_SHIELDGENERATOR3:
- return ShieldGeneratorDeactivated[2];
-
- case DATA_SHIELDGENERATOR4:
- return ShieldGeneratorDeactivated[3];
-
+ case DATA_LADYVASHJEVENT: return Encounters[5];
+ case DATA_SHIELDGENERATOR1: return ShieldGeneratorDeactivated[0];
+ case DATA_SHIELDGENERATOR2: return ShieldGeneratorDeactivated[1];
+ case DATA_SHIELDGENERATOR3: return ShieldGeneratorDeactivated[2];
+ case DATA_SHIELDGENERATOR4: return ShieldGeneratorDeactivated[3];
case DATA_CANSTARTPHASE3:
- if(ShieldGeneratorDeactivated[0] && ShieldGeneratorDeactivated[1] && ShieldGeneratorDeactivated[2] && ShieldGeneratorDeactivated[3])
- return 1;
- break;
+ if(ShieldGeneratorDeactivated[0] && ShieldGeneratorDeactivated[1] && ShieldGeneratorDeactivated[2] && ShieldGeneratorDeactivated[3])return 1;break;
}
-
return 0;
}
+ const char* Save()
+ {
+ OUT_SAVE_INST_DATA;
+ std::ostringstream stream;
+ stream << Encounters[0] << " " << Encounters[1] << " " << Encounters[2] << " "
+ << Encounters[3] << " " << Encounters[4] << " " << Encounters[5];
+ char* out = new char[stream.str().length() + 1];
+ strcpy(out, stream.str().c_str());
+ if(out)
+ {
+ OUT_SAVE_INST_DATA_COMPLETE;
+ return out;
+ }
+ return NULL;
+ }
+
+ void Load(const char* in)
+ {
+ if(!in)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+ OUT_LOAD_INST_DATA(in);
+ std::istringstream stream(in);
+ stream >> Encounters[0] >> Encounters[1] >> Encounters[2] >> Encounters[3]
+ >> Encounters[4] >> Encounters[5];
+ for(uint8 i = 0; i < ENCOUNTERS; ++i)
+ if(Encounters[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead.
+ Encounters[i] = NOT_STARTED;
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
};
InstanceData* GetInstanceData_instance_serpentshrine_cavern(Map* map)