diff options
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) |