diff options
-rw-r--r-- | src/bindings/scripts/include/sc_creature.cpp | 139 | ||||
-rw-r--r-- | src/bindings/scripts/include/sc_creature.h | 2 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp | 420 | ||||
-rw-r--r-- | src/game/CreatureAI.h | 2 | ||||
-rw-r--r-- | src/game/SpellEffects.cpp | 123 |
5 files changed, 588 insertions, 98 deletions
diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp index b1044ff6319..7bc7c1015cb 100644 --- a/src/bindings/scripts/include/sc_creature.cpp +++ b/src/bindings/scripts/include/sc_creature.cpp @@ -261,6 +261,145 @@ Unit* ScriptedAI::SelectUnit(SelectAggroTarget target, uint32 position) return NULL; } +struct TargetDistanceOrder : public std::binary_function<const Unit, const Unit, bool> +{ + const Unit* me; + TargetDistanceOrder(const Unit* Target) : me(Target) {}; + // functor for operator ">" + bool operator()(const Unit* _Left, const Unit* _Right) const + { + return (me->GetDistance(_Left) < me->GetDistance(_Right)); + } +}; + +Unit* ScriptedAI::SelectUnit(SelectAggroTarget targetType, uint32 position, float dist, bool playerOnly) +{ + if(targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST) + { + std::list<HostilReference*> &m_threatlist = m_creature->getThreatManager().getThreatList(); + if(m_threatlist.empty()) return NULL; + std::list<Unit*> targetList; + std::list<HostilReference*>::iterator itr = m_threatlist.begin(); + for(; itr!= m_threatlist.end(); ++itr) + { + Unit *target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + if(!target + || playerOnly && target->GetTypeId() != TYPEID_PLAYER + || dist && !m_creature->IsWithinDistInMap(target, dist)) + { + continue; + } + targetList.push_back(target); + } + if(position >= targetList.size()) + return NULL; + targetList.sort(TargetDistanceOrder(m_creature)); + if(targetType == SELECT_TARGET_NEAREST) + { + std::list<Unit*>::iterator i = targetList.begin(); + advance(i, position); + return *i; + } + else + { + std::list<Unit*>::reverse_iterator i = targetList.rbegin(); + advance(i, position); + return *i; + } + } + else + { + std::list<HostilReference*> m_threatlist = m_creature->getThreatManager().getThreatList(); + std::list<HostilReference*>::iterator i; + Unit *target; + while(position < m_threatlist.size()) + { + if(targetType == SELECT_TARGET_BOTTOMAGGRO) + { + i = m_threatlist.end(); + advance(i, - (int32)position - 1); + } + else + { + i = m_threatlist.begin(); + if(targetType == SELECT_TARGET_TOPAGGRO) + advance(i, position); + else // random + advance(i, position + rand()%(m_threatlist.size() - position)); + } + + target = Unit::GetUnit(*m_creature,(*i)->getUnitGuid()); + if(!target + || playerOnly && target->GetTypeId() != TYPEID_PLAYER + || dist && !m_creature->IsWithinDistInMap(target, dist)) + { + m_threatlist.erase(i); + } + else + { + return target; + } + } + } + + return NULL; +} + +void ScriptedAI::SelectUnitList(std::list<Unit*> &targetList, uint32 num, SelectAggroTarget targetType, float dist, bool playerOnly) +{ + if(targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST) + { + std::list<HostilReference*> &m_threatlist = m_creature->getThreatManager().getThreatList(); + if(m_threatlist.empty()) return; + std::list<HostilReference*>::iterator itr = m_threatlist.begin(); + for(; itr!= m_threatlist.end(); ++itr) + { + Unit *target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); + if(!target + || playerOnly && target->GetTypeId() != TYPEID_PLAYER + || dist && !m_creature->IsWithinDistInMap(target, dist)) + { + continue; + } + targetList.push_back(target); + } + targetList.sort(TargetDistanceOrder(m_creature)); + targetList.resize(num); + if(targetType == SELECT_TARGET_FARTHEST) + targetList.reverse(); + } + else + { + std::list<HostilReference*> m_threatlist = m_creature->getThreatManager().getThreatList(); + std::list<HostilReference*>::iterator i; + Unit *target; + while(m_threatlist.size()) + { + if(targetType == SELECT_TARGET_BOTTOMAGGRO) + { + i = m_threatlist.end(); + --i; + } + else + { + i = m_threatlist.begin(); + if(targetType == SELECT_TARGET_RANDOM) + advance(i, rand()%m_threatlist.size()); + } + + target = Unit::GetUnit(*m_creature,(*i)->getUnitGuid()); + m_threatlist.erase(i); + if(!target + || playerOnly && target->GetTypeId() != TYPEID_PLAYER + || dist && !m_creature->IsWithinDistInMap(target, dist)) + { + continue; + } + targetList.push_back(target); + } + } +} + SpellEntry const* ScriptedAI::SelectSpell(Unit* Target, int32 School, int32 Mechanic, SelectTarget Targets, uint32 PowerCostMin, uint32 PowerCostMax, float RangeMin, float RangeMax, SelectEffect Effects) { //No target so we can't cast diff --git a/src/bindings/scripts/include/sc_creature.h b/src/bindings/scripts/include/sc_creature.h index 494ab101f08..e85e7d45f8f 100644 --- a/src/bindings/scripts/include/sc_creature.h +++ b/src/bindings/scripts/include/sc_creature.h @@ -146,6 +146,8 @@ struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI //Selects a unit from the creature's current aggro list Unit* SelectUnit(SelectAggroTarget target, uint32 position); + Unit* SelectUnit(SelectAggroTarget target, uint32 position, float dist, bool playerOnly); + void SelectUnitList(std::list<Unit*> &targetList, uint32 num, SelectAggroTarget target, float dist, bool playerOnly); //Returns spells that meet the specified criteria from the creatures spell list SpellEntry const* SelectSpell(Unit* Target, int32 School, int32 Mechanic, SelectTarget Targets, uint32 PowerCostMin, uint32 PowerCostMax, float RangeMin, float RangeMax, SelectEffect Effect); diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp index a4da476a408..2ba76a57bd5 100644 --- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp @@ -16,46 +16,78 @@ /* ScriptData SDName: Boss_Fathomlord_Karathress -SD%Complete: 50 -SDComment: Missing Multishot, pet, Totems, Windfury, Whirlwind +SD%Complete: 70% +SDComment: Cyclone workaround SDCategory: Coilfang Resevoir, Serpent Shrine Cavern EndScriptData */ #include "precompiled.h" #include "def_serpent_shrine.h" +#include "../../../npc/npc_escortAI.h" //Karathress spells -#define SPELL_CATACLYSMIC_BOLT 38441 -#define SPELL_POWER_OF_SHARKKIS 38455 -#define SPELL_POWER_OF_TIDALVESS 38452 -#define SPELL_POWER_OF_CARIBDIS 38451 -#define SPELL_ENRAGE 24318 +#define SPELL_CATACLYSMIC_BOLT 38441 +#define SPELL_POWER_OF_SHARKKIS 38455 +#define SPELL_POWER_OF_TIDALVESS 38452 +#define SPELL_POWER_OF_CARIBDIS 38451 +#define SPELL_ENRAGE 45078 +#define SPELL_SEAR_NOVA 38445 +#define SPELL_BLESSING_OF_THE_TIDES 38449 + //Sharkkis spells -#define SPELL_LEECHING_THROW 29436 -#define SPELL_THE_BEAST_WITHIN 38373 +#define SPELL_LEECHING_THROW 29436 +#define SPELL_THE_BEAST_WITHIN 38373 +#define SPELL_LEECHING_THROW 29436 +#define SPELL_MULTISHOT 38366 +#define SPELL_THE_BEAST_WITHIN 38373 +#define SPELL_SUMMON_FATHOM_LURKER 38433 +#define SPELL_SUMMON_FATHOM_SPOREBAT 38431 +#define SPELL_PET_ENRAGE 19574 + //Tidalvess spells -#define SPELL_FROST_SHOCK 38234 +#define SPELL_FROST_SHOCK 38234 +#define SPELL_SPITFIRE_TOTEM 38236 +#define SPELL_POISON_CLEANSING_TOTEM 38306 +#define SPELL_POISON_CLEANSING_EFFECT 8167 +#define SPELL_EARTHBIND_TOTEM 38304 +#define SPELL_EARTHBIND_TOTEM_EFFECT 6474 +#define SPELL_WINDFURY_WEAPON 32911 + //Caribdis Spells -#define SPELL_WATER_BOLT_VOLLEY 38335 -#define SPELL_TIDAL_SURGE 38353 -#define SPELL_HEAL 41386 - -#define SAY_AGGRO "Guards, attention! We have visitors..." -#define SAY_SLAY1 "I am rid of you." -#define SAY_GAIN_ABILITY1 "I am more powerful than ever!" -#define SAY_GAIN_ABILITY2 "Go on, kill them! I'll be the better for it!" -#define SAY_GAIN_ABILITY3 "More knowledge, more power!" -#define SAY_DEATH "Her ... excellency ... awaits!" - -#define SOUND_AGGRO 11277 -#define SOUND_PLYR_ATTACK 11278 -#define SOUND_GAIN_ABILITY1 11279 -#define SOUND_GAIN_ABILITY2 11280 -#define SOUND_GAIN_ABILITY3 11281 -#define SOUND_SLAY1 11282 -#define SOUND_SLAY2 11283 -#define SOUND_SLAY3 11284 -#define SOUND_DEATH 11285 +#define SPELL_WATER_BOLT_VOLLEY 38335 +#define SPELL_TIDAL_SURGE 38358 +#define SPELL_TIDAL_SURGE_FREEZE 38357 +#define SPELL_HEAL 41386 +#define SPELL_SUMMON_CYCLONE 38337 +#define SPELL_CYCLONE_CYCLONE 29538 + +//Yells and Quotes +#define SAY_AGGRO "Guards, attention! We have visitors..." +#define SOUND_AGGRO 11277 +#define SAY_SLAY1 "I am rid of you." +#define SOUND_SLAY1 11282 +#define SAY_SLAY2 "Land-dwelling scum!" +#define SOUND_SLAY2 11284 +#define SAY_GAIN_ABILITY1 "I am more powerful than ever!" +#define SOUND_GAIN_ABILITY1 11279 +#define SAY_GAIN_ABILITY2 "Go on, kill them! I'll be the better for it!" +#define SOUND_GAIN_ABILITY2 11280 +#define SAY_GAIN_ABILITY3 "More knowledge, more power!" +#define SOUND_GAIN_ABILITY3 11281 +#define SAY_DEATH "Her ... excellency ... awaits!" +#define SOUND_DEATH 11285 +#define SAY_GAIN_BLESSING_OF_TIDES "Your overconfidence will be your undoing! Guards, lend me your strength!" +#define SOUND_GAIN_BLESSING_OF_TIDES 11278 +#define SAY_MISC "Alana be'lendor!" //don't know what use this +#define SOUND_MISC 11283 + +//Summoned Unit GUIDs +#define CREATURE_CYCLONE 22104 +#define CREATURE_FATHOM_SPOREBAT 22120 +#define CREATURE_FATHOM_LURKER 22119 +#define CREATURE_SPITFIRE_TOTEM 22091 +#define CREATURE_EARTHBIND_TOTEM 22486 +#define CREATURE_POISON_CLEANSING_TOTEM 22487 //entry and position for Seer Olum #define SEER_OLUM 22820 @@ -80,6 +112,9 @@ struct TRINITY_DLL_DECL boss_fathomlord_karathressAI : public ScriptedAI uint32 CataclysmicBolt_Timer; uint32 Enrage_Timer; + uint32 SearNova_Timer; + + bool BlessingOfTides; uint64 Advisors[3]; @@ -87,27 +122,38 @@ struct TRINITY_DLL_DECL boss_fathomlord_karathressAI : public ScriptedAI { CataclysmicBolt_Timer = 10000; Enrage_Timer = 600000; //10 minutes - - Creature* Advisor; - for(uint8 i = 0; i < 3; ++i) - if(Advisors[i]) - { - Advisor = ((Creature*)Unit::GetUnit(*m_creature, Advisors[i])); - if(Advisor) - { - if(Advisor->isAlive()) - { - Advisor->DealDamage(Advisor, Advisor->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - Advisor->RemoveCorpse(); - Advisor->Respawn(); - } - Advisor->AI()->EnterEvadeMode(); - } - } - - if( pInstance ) - pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); - } + SearNova_Timer = 20000+rand()%40000; // 20 - 60 seconds + + BlessingOfTides = false; + + + + if(pInstance) + { + uint64 RAdvisors[3]; + RAdvisors[0] = pInstance->GetData64(DATA_SHARKKIS); + RAdvisors[1] = pInstance->GetData64(DATA_TIDALVESS); + RAdvisors[2] = pInstance->GetData64(DATA_CARIBDIS); + //Respawn of the 3 Advisors + Creature* pAdvisor = NULL; + for( int i=0; i<3; i++ ) + + + if(RAdvisors[i]) + { + pAdvisor = ((Creature*)Unit::GetUnit((*m_creature), RAdvisors[i])); + if(pAdvisor && !pAdvisor->isAlive()) + { + pAdvisor->Respawn(); + pAdvisor->AI()->EnterEvadeMode(); + pAdvisor->GetMotionMaster()->MoveTargetedHome(); + } + } + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + + } void EventSharkkisDeath() { @@ -149,6 +195,7 @@ struct TRINITY_DLL_DECL boss_fathomlord_karathressAI : public ScriptedAI DoPlaySoundToSet(m_creature, SOUND_AGGRO); DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); + DoZoneInCombat(); pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); @@ -164,9 +211,7 @@ struct TRINITY_DLL_DECL boss_fathomlord_karathressAI : public ScriptedAI break; case 1: DoPlaySoundToSet(m_creature, SOUND_SLAY2); - break; - case 2: - DoPlaySoundToSet(m_creature, SOUND_SLAY3); + DoYell(SAY_SLAY2, LANG_UNIVERSAL, NULL); break; } } @@ -177,7 +222,7 @@ struct TRINITY_DLL_DECL boss_fathomlord_karathressAI : public ScriptedAI DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); if( pInstance ) - pInstance->SetData(DATA_FATHOMLORDKARATHRESSEVENT, NOT_STARTED); + pInstance->SetData(DATA_FATHOMLORDKARATHRESSEVENT, DONE); //support for quest 10944 m_creature->SummonCreature(SEER_OLUM, OLUM_X, OLUM_Y, OLUM_Z, OLUM_O, TEMPSUMMON_TIMED_DESPAWN, 3600000); @@ -208,7 +253,10 @@ struct TRINITY_DLL_DECL boss_fathomlord_karathressAI : public ScriptedAI //someone evaded! if(pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + { EnterEvadeMode(); + return; + } //CataclysmicBolt_Timer if(CataclysmicBolt_Timer < diff) @@ -226,6 +274,13 @@ struct TRINITY_DLL_DECL boss_fathomlord_karathressAI : public ScriptedAI CataclysmicBolt_Timer = 10000; }else CataclysmicBolt_Timer -= diff; + //SearNova_Timer + if(SearNova_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SEAR_NOVA); + SearNova_Timer = 20000+rand()%40000; + }else SearNova_Timer -= diff; + //Enrage_Timer if(Enrage_Timer < diff) { @@ -233,6 +288,33 @@ struct TRINITY_DLL_DECL boss_fathomlord_karathressAI : public ScriptedAI Enrage_Timer = 90000; }else Enrage_Timer -= diff; + //Blessing of Tides Trigger + if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) <= 75 && !BlessingOfTides) + { + BlessingOfTides = true; + bool continueTriggering; + Creature* Advisor; + for(uint8 i = 0; i < 4; ++i) + if(Advisors[i]) + { + Advisor = ((Creature*)Unit::GetUnit(*m_creature, Advisors[i])); + if(Advisor) + { + if(Advisor->isAlive()) + { + continueTriggering = true; + break; + } + } + } + if( continueTriggering ) + { + DoCast(m_creature, SPELL_BLESSING_OF_THE_TIDES); + DoYell(SAY_GAIN_BLESSING_OF_TIDES, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(m_creature, SOUND_GAIN_BLESSING_OF_TIDES); + } + } + DoMeleeAttackIfReady(); } }; @@ -250,11 +332,30 @@ struct TRINITY_DLL_DECL boss_fathomguard_sharkkisAI : public ScriptedAI uint32 LeechingThrow_Timer; uint32 TheBeastWithin_Timer; + uint32 Multishot_Timer; + uint32 Pet_Timer; + + bool pet; + + uint64 SummonedPet; + void Reset() { LeechingThrow_Timer = 20000; TheBeastWithin_Timer = 30000; + Multishot_Timer = 15000; + Pet_Timer = 10000; + + pet = false; + + Creature *Pet = (Creature*) Unit::GetUnit(*m_creature, SummonedPet); + if( Pet && Pet->isAlive() ) + { + Pet->DealDamage( Pet, Pet->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false ); + } + + SummonedPet = 0; if( pInstance ) pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); @@ -268,7 +369,8 @@ struct TRINITY_DLL_DECL boss_fathomguard_sharkkisAI : public ScriptedAI Karathress = (Creature*)(Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KARATHRESS))); if(Karathress) - ((boss_fathomlord_karathressAI*)Karathress->AI())->EventSharkkisDeath(); + if(!m_creature->isAlive() && Karathress) + ((boss_fathomlord_karathressAI*)Karathress->AI())->EventSharkkisDeath(); } } @@ -300,7 +402,10 @@ struct TRINITY_DLL_DECL boss_fathomguard_sharkkisAI : public ScriptedAI //someone evaded! if(pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) - EnterEvadeMode(); + { + EnterEvadeMode(); + return; + } //LeechingThrow_Timer if(LeechingThrow_Timer < diff) @@ -309,12 +414,51 @@ struct TRINITY_DLL_DECL boss_fathomguard_sharkkisAI : public ScriptedAI LeechingThrow_Timer = 20000; }else LeechingThrow_Timer -= diff; - //TheBeastWithin_Timer - if(TheBeastWithin_Timer < diff) - { - DoCast(m_creature, SPELL_THE_BEAST_WITHIN); - TheBeastWithin_Timer = 30000; - }else TheBeastWithin_Timer -= diff; + //Multishot_Timer + if(Multishot_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_MULTISHOT); + Multishot_Timer = 20000; + }else Multishot_Timer -= diff; + + //TheBeastWithin_Timer + if(TheBeastWithin_Timer < diff) + { + DoCast(m_creature, SPELL_THE_BEAST_WITHIN); + Creature *Pet = (Creature*) Unit::GetUnit(*m_creature, SummonedPet); + if( Pet && Pet->isAlive() ) + { + Pet->CastSpell( Pet, SPELL_PET_ENRAGE, true ); + } + TheBeastWithin_Timer = 30000; + }else TheBeastWithin_Timer -= diff; + + //Pet_Timer + if(Pet_Timer < diff && pet == false) + { + pet = true; + //uint32 spell_id; + uint32 pet_id; + switch( rand()%2 ) + { + case 0: + //spell_id = SPELL_SUMMON_FATHOM_LURKER; + pet_id = CREATURE_FATHOM_LURKER; + break; + case 1: + //spell_id = SPELL_SUMMON_FATHOM_SPOREBAT; + pet_id = CREATURE_FATHOM_SPOREBAT; + break; + } + //DoCast( m_creature, spell_id, true ); + Creature *Pet = DoSpawnCreature(pet_id,0,0,0,0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000 ); + Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0); + if (Pet && target) + { + Pet->AI()->AttackStart(target); + SummonedPet = Pet->GetGUID(); + } + }else Pet_Timer -= diff; DoMeleeAttackIfReady(); } @@ -332,10 +476,16 @@ struct TRINITY_DLL_DECL boss_fathomguard_tidalvessAI : public ScriptedAI ScriptedInstance* pInstance; uint32 FrostShock_Timer; + uint32 Spitfire_Timer; + uint32 PoisonCleansing_Timer; + uint32 Earthbind_Timer; void Reset() { FrostShock_Timer = 25000; + Spitfire_Timer = 60000; + PoisonCleansing_Timer = 30000; + Earthbind_Timer = 45000; if( pInstance ) pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); @@ -349,7 +499,8 @@ struct TRINITY_DLL_DECL boss_fathomguard_tidalvessAI : public ScriptedAI Karathress = (Creature*)(Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KARATHRESS))); if(Karathress) - ((boss_fathomlord_karathressAI*)Karathress->AI())->EventTidalvessDeath(); + if(!m_creature->isAlive() && Karathress) + ((boss_fathomlord_karathressAI*)Karathress->AI())->EventTidalvessDeath(); } } @@ -360,6 +511,7 @@ struct TRINITY_DLL_DECL boss_fathomguard_tidalvessAI : public ScriptedAI pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); } + DoCast(m_creature, SPELL_WINDFURY_WEAPON); } void UpdateAI(const uint32 diff) @@ -381,7 +533,15 @@ struct TRINITY_DLL_DECL boss_fathomguard_tidalvessAI : public ScriptedAI //someone evaded! if(pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + { EnterEvadeMode(); + return; + } + + if( !m_creature->HasAura(SPELL_WINDFURY_WEAPON, 0) ) + { + DoCast(m_creature, SPELL_WINDFURY_WEAPON); + } //FrostShock_Timer if(FrostShock_Timer < diff) @@ -390,6 +550,32 @@ struct TRINITY_DLL_DECL boss_fathomguard_tidalvessAI : public ScriptedAI FrostShock_Timer = 25000+rand()%5000; }else FrostShock_Timer -= diff; + //Spitfire_Timer + if(Spitfire_Timer < diff) + { + DoCast(m_creature, SPELL_SPITFIRE_TOTEM); + Unit *SpitfireTotem = Unit::GetUnit( *m_creature, CREATURE_SPITFIRE_TOTEM ); + if( SpitfireTotem ) + { + ((Creature*)SpitfireTotem)->AI()->AttackStart( m_creature->getVictim() ); + } + Spitfire_Timer = 60000; + }else Spitfire_Timer -= diff; + + //PoisonCleansing_Timer + if(PoisonCleansing_Timer < diff) + { + DoCast(m_creature, SPELL_POISON_CLEANSING_TOTEM); + PoisonCleansing_Timer = 30000; + }else PoisonCleansing_Timer -= diff; + + //Earthbind_Timer + if(Earthbind_Timer < diff) + { + DoCast(m_creature, SPELL_EARTHBIND_TOTEM); + Earthbind_Timer = 45000; + }else Earthbind_Timer -= diff; + DoMeleeAttackIfReady(); } }; @@ -408,12 +594,14 @@ struct TRINITY_DLL_DECL boss_fathomguard_caribdisAI : public ScriptedAI uint32 WaterBoltVolley_Timer; uint32 TidalSurge_Timer; uint32 Heal_Timer; + uint32 Cyclone_Timer; void Reset() { WaterBoltVolley_Timer = 35000; TidalSurge_Timer = 15000+rand()%5000; Heal_Timer = 55000; + Cyclone_Timer = 30000+rand()%10000; if(pInstance) pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); @@ -427,7 +615,8 @@ struct TRINITY_DLL_DECL boss_fathomguard_caribdisAI : public ScriptedAI Karathress = (Creature*)(Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KARATHRESS))); if(Karathress) - ((boss_fathomlord_karathressAI*)Karathress->AI())->EventCaribdisDeath(); + if(!m_creature->isAlive() && Karathress) + ((boss_fathomlord_karathressAI*)Karathress->AI())->EventCaribdisDeath(); } } @@ -459,7 +648,10 @@ struct TRINITY_DLL_DECL boss_fathomguard_caribdisAI : public ScriptedAI //someone evaded! if(pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + { EnterEvadeMode(); + return; + } //WaterBoltVolley_Timer if(WaterBoltVolley_Timer < diff) @@ -472,42 +664,74 @@ struct TRINITY_DLL_DECL boss_fathomguard_caribdisAI : public ScriptedAI if(TidalSurge_Timer < diff) { DoCast(m_creature->getVictim(), SPELL_TIDAL_SURGE); + // Hacky way to do it - won't trigger elseways + m_creature->getVictim()->CastSpell( m_creature->getVictim(), SPELL_TIDAL_SURGE_FREEZE, true ); TidalSurge_Timer = 15000+rand()%5000; }else TidalSurge_Timer -= diff; - //Heal_Timer - if(Heal_Timer < diff) - { - // It can be cast on any of the mobs - Unit *pUnit = NULL; - - if(pInstance) - { - switch(rand()%4) - { - case 0: - pUnit = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KARATHRESS)); - break; - case 1: - pUnit = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_SHARKKIS)); - break; - case 2: - pUnit = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_TIDALVESS)); - break; - case 3: - pUnit = m_creature; - break; - } - }else pUnit = m_creature; - - if(pUnit && pUnit->isAlive()) - DoCast(pUnit, SPELL_HEAL); - - Heal_Timer = 60000; - }else Heal_Timer -= diff; - - DoMeleeAttackIfReady(); - } + //Cyclone_Timer + if(Cyclone_Timer < diff) + { + //DoCast(m_creature, SPELL_SUMMON_CYCLONE); // Doesn't work + Cyclone_Timer = 30000+rand()%10000; + Creature *Cyclone = m_creature->SummonCreature(CREATURE_CYCLONE, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 15000); + if( Cyclone ) + { + ((Creature*)Cyclone)->SetFloatValue(OBJECT_FIELD_SCALE_X, 3.0f); + Cyclone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Cyclone->setFaction(m_creature->getFaction()); + Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_CYCLONE, true); + Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if( target ) + { + Cyclone->AI()->AttackStart(target); + } + } + }else Cyclone_Timer -= diff; + + //Heal_Timer + if(Heal_Timer < diff) + { + // It can be cast on any of the mobs + Unit *pUnit = NULL; + + while( pUnit == NULL || !pUnit->isAlive() ) + { + pUnit = selectAdvisorUnit(); + } + + if(pUnit && pUnit->isAlive()) + DoCast(pUnit, SPELL_HEAL); + Heal_Timer = 60000; + }else Heal_Timer -= diff; + + DoMeleeAttackIfReady(); + } + + Unit* selectAdvisorUnit() + { + Unit* pUnit; + if(pInstance) + { + switch(rand()%4) + { + case 0: + pUnit = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KARATHRESS)); + break; + case 1: + pUnit = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_SHARKKIS)); + break; + case 2: + pUnit = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_TIDALVESS)); + break; + case 3: + pUnit = m_creature; + break; + } + }else pUnit = m_creature; + + return pUnit; + } }; CreatureAI* GetAI_boss_fathomlord_karathress(Creature *_Creature) diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h index 03782cc6764..d44ab81bd3a 100644 --- a/src/game/CreatureAI.h +++ b/src/game/CreatureAI.h @@ -65,6 +65,8 @@ enum SelectAggroTarget SELECT_TARGET_RANDOM = 0, //Just selects a random target SELECT_TARGET_TOPAGGRO, //Selects targes from top aggro to bottom SELECT_TARGET_BOTTOMAGGRO, //Selects targets from bottom aggro to top + SELECT_TARGET_NEAREST, + SELECT_TARGET_FARTHEST, }; class TRINITY_DLL_SPEC CreatureAI diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 90dc40c89fc..419a9820ba3 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -615,6 +615,103 @@ void Spell::EffectDummy(uint32 i) // Gnomish Poultryizer trinket switch(m_spellInfo->Id ) { + // Mingo's Fortune Giblets + case 40802: + { + if (m_caster->GetTypeId() != TYPEID_PLAYER) return; + + Player *player = (Player*)m_caster; + uint32 newitemid; + + switch(urand(1,20)) + { + case 1: newitemid = 32688; break; + case 2: newitemid = 32689; break; + case 3: newitemid = 32690; break; + case 4: newitemid = 32691; break; + case 5: newitemid = 32692; break; + case 6: newitemid = 32693; break; + case 7: newitemid = 32700; break; + case 8: newitemid = 32701; break; + case 9: newitemid = 32702; break; + case 10: newitemid = 32703; break; + case 11: newitemid = 32704; break; + case 12: newitemid = 32705; break; + case 13: newitemid = 32706; break; + case 14: newitemid = 32707; break; + case 15: newitemid = 32708; break; + case 16: newitemid = 32709; break; + case 17: newitemid = 32710; break; + case 18: newitemid = 32711; break; + case 19: newitemid = 32712; break; + case 20: newitemid = 32713; break; + } + ItemPosCountVec dest; + uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, 1, false); + if (msg != EQUIP_ERR_OK) + { + player->SendEquipError(msg, NULL, NULL); + return; + } + Item *pItem = player->StoreNewItem(dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid)); + + if (!pItem) + { + player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); + return; + } + player->SendNewItem(pItem, 1, true, true); + + return; + } + // Encapsulate Voidwalker + case 29364: + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet()) return; + + Creature* creatureTarget = (Creature*)unitTarget; + GameObject* pGameObj = new GameObject; + + if (!creatureTarget || !pGameObj) return; + + if (!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 181574, creatureTarget->GetMap(), + creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), + creatureTarget->GetOrientation(), 0, 0, 0, 0, 100, 1)) + { + delete pGameObj; + return; + } + + pGameObj->SetRespawnTime(0); + pGameObj->SetOwnerGUID(m_caster->GetGUID()); + pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()); + pGameObj->SetSpellId(m_spellInfo->Id); + + MapManager::Instance().GetMap(creatureTarget->GetMapId(), pGameObj)->Add(pGameObj); + + WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8); + data << uint64(pGameObj->GetGUID()); + m_caster->SendMessageToSet(&data,true); + + return; + } + // Demon Broiled Surprise + case 43723: + { + if (!unitTarget || unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || + ((Creature*)unitTarget)->isPet()) return; + + Player *player = (Player*)m_caster; + + if (!player) return; + + player->CastSpell(unitTarget, 43753, true); + + if (player->GetQuestStatus(11379) == QUEST_STATUS_INCOMPLETE && unitTarget->GetEntry() == 19973) + player->CastedCreatureOrGO(19973, unitTarget->GetGUID(), 43723); + + return; + } case 8063: // Deviate Fish { if(m_caster->GetTypeId() != TYPEID_PLAYER) @@ -4788,6 +4885,32 @@ void Spell::EffectScriptEffect(uint32 effIndex) case 40904: unitTarget->CastSpell(m_caster, 40903, true); break; // Flame Crash case 41126: unitTarget->CastSpell(unitTarget, 41131, true); break; + case 41931: + { + int bag=19; + int slot=0; + Item* item = NULL; + + while (bag < 256) + { + item = ((Player*)m_caster)->GetItemByPos(bag,slot); + if (item && item->GetEntry() == 38587) break; + slot++; + if (slot == 39) + { + slot = 0; + bag++; + } + } + if (bag < 256) + { + if (((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount() == 1) ((Player*)m_caster)->RemoveItem(bag,slot,true); + else ((Player*)m_caster)->GetItemByPos(bag,slot)->SetCount(((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount()-1); + // Spell 42518 (Braufest - Gratisprobe des Braufest herstellen) + m_caster->CastSpell(m_caster,42518,true); + return; + } + } // Force Cast - Portal Effect: Sunwell Isle case 44876: unitTarget->CastSpell(unitTarget, 44870, true); break; //5,000 Gold |