Example #1
0
    void UpdateAI(const uint32 uiDiff)
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        //m_uiPoisonBolt_Timer
        if (m_uiPoisonBolt_Timer < uiDiff)
        {
            Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0);

            if (pTarget && pTarget->IsWithinDistInMap(m_creature, 30.0f))
                DoCastSpellIfCan(pTarget, SPELL_POISON_BOLT);

            m_uiPoisonBolt_Timer = urand(5000, 10000);
        } else m_uiPoisonBolt_Timer -= uiDiff;
    }
            void UpdateAI(const uint32 diff)
            {
                if (!UpdateVictim())
                    return;

                if (flashheal_timer <= diff)
                {
                    Unit* target = DoSelectLowestHpFriendly(99, 30000);
                    if (target)
                    {
                        if (target->IsWithinDistInMap(me, 50))
                            DoCast(target, SPELL_FLASH_HEAL, false);
                        else
                        {
                            // bugged
                            //me->GetMotionMaster()->Clear();
                            //me->GetMotionMaster()->MoveChase(target, 20);
                        }
                    }
                    else
                    {
                        if (urand(0, 1))
                            target = DoSelectLowestHpFriendly(50, 0);
                        else
                            target = SelectTarget(SELECT_TARGET_RANDOM, 0);
                        if (target)
                            DoCast(target, SPELL_DISPEL_MAGIC, false);
                    }
                    flashheal_timer = 2500;
                } else flashheal_timer -= diff;

                /*if (dispelmagic_timer <= diff)
                {
                if (urand(0, 1))
                {
                    Unit* target = SelectTarget();

                    DoCast(target, SPELL_DISPEL_MAGIC, false);
                }
                else
                    me->CastSpell(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DISPEL_MAGIC, false);

                dispelmagic_timer = 12000;
                } else dispelmagic_timer -= diff;*/

                boss_hexlord_addAI::UpdateAI(diff);
            }
Example #3
0
    void GeddonArmageddonDealDamage()
    {
        std::vector<ObjectGuid> vGuids;
        m_creature->FillGuidsListFromThreatList(vGuids);
        if (vGuids.empty())
            return;

        for (std::vector<ObjectGuid>::const_iterator itr = vGuids.begin(); itr != vGuids.end(); ++itr)
        {
            Unit* pTarget = m_creature->GetMap()->GetUnit(*itr);
			if (pTarget && pTarget->IsWithinDistInMap(m_creature, 20.0f) && pTarget->IsWithinLOSInMap(m_creature))
				m_creature->DealDamage(pTarget, urand(7600, 8400), NULL, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_FIRE, NULL, false);
        }

        m_creature->SetHealth(0);
        m_creature->SetDeathState(JUST_DIED);
    }
Example #4
0
        void UpdateAI(uint32 diff) override
        {
            // PoisonBoltTimer
            if (PoisonBoltTimer <= diff)
            {
                Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0);

                if (target && target->IsWithinDistInMap(me, 30))
                    DoCast(target, SPELL_POISON_BOLT);

                PoisonBoltTimer = 5000 + rand32() % 5000;
            } else PoisonBoltTimer -= diff;

            // DespawnTimer
            if (DespawnTimer <= diff)
            {
                // call Unsummon()
                me->setDeathState(DEAD);

                // to prevent crashes
                DespawnTimer = 1000;
            } else DespawnTimer -= diff;
        }
Example #5
0
            void UpdateAI(uint32 diff)
            {
                if (!UpdateVictim())
                    return;

                if (me->HasUnitState(UNIT_STATE_CASTING))
                    return;

                if (m_uiCheckTimer <= diff)
                {
                    Unit *pTarget;
                    std::list<HostileReference *> t_list = me->getThreatManager().getThreatList();
                    for (std::list<HostileReference *>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
                    {
						pTarget = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
                        if (pTarget && pTarget->IsWithinDistInMap(me, 12))
                        {
                            me->AddAura(SPELL_ADRENALINE, pTarget);
                            m_uiCheckTimer = 1000;
                        }
                    }
                } else 
                    m_uiCheckTimer -= diff;
            }
Example #6
0
    void UpdateAI(const uint32 diff)
    {
        //PoisonBolt_Timer
        if (PoisonBolt_Timer <= diff)
        {
            Unit *pTarget = NULL;
            pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0);

            if (pTarget && pTarget->IsWithinDistInMap(m_creature, 30))
                DoCast(pTarget, SPELL_POISON_BOLT);

            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;
    }
Example #7
0
    void UpdateAI(const uint32 diff)
    {
        //Return since we have no target
        if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() )
            return;

        //Earthquake_Timer
        if(Earthquake_Timer < diff)
        {
            if(!Earthquake)
            {
                DoCast(m_creature->getVictim(), SPELL_EARTHQUAKE);
                Earthquake = true;
                Earthquake_Timer = 10000;
            }
            else
            {
                switch(rand()%2)
                {
                    case 0:
                    DoPlaySoundToSet(m_creature, SOUND_SUMMON1);
                    DoYell(SAY_SUMMON1, LANG_UNIVERSAL, NULL);
                    break;

                    case 1:
                    DoPlaySoundToSet(m_creature, SOUND_SUMMON2);
                    DoYell(SAY_SUMMON2, LANG_UNIVERSAL, NULL);
                    break;
                }

                //north
                SummonMurloc(486.10, -723.64, -7.14);
                SummonMurloc(482.58, -723.78, -7.14);
                SummonMurloc(479.38, -723.91, -7.14);
                SummonMurloc(476.03, -723.86, -7.14);
                SummonMurloc(472.69, -723.69, -7.14);
                SummonMurloc(469.04, -723.63, -7.14);

                //south
                SummonMurloc(311.63, -725.04, -13.15);
                SummonMurloc(307.81, -725.34, -13.15);
                SummonMurloc(303.91, -725.64, -13.06);
                SummonMurloc(300.23, -726, -11.89);
                SummonMurloc(296.82, -726.33, -10.82);
                SummonMurloc(293.64, -726.64, -9.81);

                DoTextEmote(EMOTE_EARTHQUAKE, NULL);

                Earthquake = false;
                Earthquake_Timer = 40000+rand()%5000;
            }
        }else Earthquake_Timer -= diff;

        //TidalWave_Timer
        if(TidalWave_Timer < diff)
        {
            DoCast(m_creature->getVictim(), SPELL_TIDAL_WAVE);
            TidalWave_Timer = 20000;
        }else TidalWave_Timer -= diff;

        if(!Phase2)
        {
            //WateryGrave_Timer
            if(WateryGrave_Timer < diff)
            {
                //Teleport 4 players under the waterfalls
                Unit *target;
                for(uint8 i = 0; i < 4; i++)
                {
                    target = SelectUnit(SELECT_TARGET_RANDOM, 1);
                    if(target && (target->GetTypeId() == TYPEID_PLAYER) && !target->HasAura(SPELL_WATERY_GRAVE, 0) && target->IsWithinDistInMap(m_creature, 50))
                        ApplyWateryGrave(target, i);
                }

                switch(rand()%2)
                {
                case 0:
                    DoPlaySoundToSet(m_creature, SOUND_SUMMON_BUBL1);
                    DoYell(SAY_SUMMON_BUBL1, LANG_UNIVERSAL, NULL);
                    break;

                case 1:
                    DoPlaySoundToSet(m_creature, SOUND_SUMMON_BUBL2);
                    DoYell(SAY_SUMMON_BUBL2, LANG_UNIVERSAL, NULL);
                    break;

                case 2:
                    break;
                }

                DoTextEmote(EMOTE_WATERY_GRAVE, NULL);

                WateryGrave_Timer = 30000;
            }else WateryGrave_Timer -= diff;

            //Start Phase2
            if((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 25)
                Phase2 = true;
        }
        else
        {
            //WateryGlobules_Timer
            if(WateryGlobules_Timer < diff)
            {
                SummonWaterGlobule(WATERY_GRAVE_X1, WATERY_GRAVE_Y1, WATERY_GRAVE_Z1);
                SummonWaterGlobule(WATERY_GRAVE_X2, WATERY_GRAVE_Y2, WATERY_GRAVE_Z2);
                SummonWaterGlobule(WATERY_GRAVE_X3, WATERY_GRAVE_Y3, WATERY_GRAVE_Z3);
                SummonWaterGlobule(WATERY_GRAVE_X4, WATERY_GRAVE_Y4, WATERY_GRAVE_Z4);

                DoTextEmote(EMOTE_WATERY_GLOBULES, NULL);

                WateryGlobules_Timer = 25000;
            }else WateryGlobules_Timer -= diff;
        }

        DoMeleeAttackIfReady();
    }
    void UpdateAI(const uint32 diff)
    {
        //Sounds OOC, Kiljaeden Orders
        if(!m_creature->getVictim())
        {
            if(m_uiKJOrdersTimer < diff)
            {
		        switch (rand()%5)
		        {
			        case 0: DoPlaySoundToSet(m_creature, SAY_KJ_OFFCOMBAT1); break;
			        case 1: DoPlaySoundToSet(m_creature, SAY_KJ_OFFCOMBAT2); break;
			        case 2: DoPlaySoundToSet(m_creature, SAY_KJ_OFFCOMBAT3); break;
                    case 3: DoPlaySoundToSet(m_creature, SAY_KJ_OFFCOMBAT4); break;
                    case 4: DoPlaySoundToSet(m_creature, SAY_KJ_OFFCOMBAT5); break;
		        }
                m_uiKJOrdersTimer = 30000;
            }else m_uiKJOrdersTimer -= diff;
        }

        /*//Rebirth After Phase1
		if(pInstance && pInstance->GetData(DATA_KILJAEDEN) == IN_PROGRESS)
        {
            m_creature->setFaction(14);
            m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
            //pInstance->SetData(DATA_KILJAEDEN_EVENT, IN_PROGRESS);
            //pInstance->SetData(DATA_DECIVER, NOT_STARTED); 
        }*/

        if(!m_creature->SelectHostileTarget() || !m_creature->getVictim())
               return;

		//dragon cast blue shield
        for(uint8 i=0; i<4; ++i)
        {
            if(Unit* Dragon = Unit::GetUnit(*m_creature, DragonGUID[i]))
                if(Dragon && Dragon->HasAura(SPELL_SHIELD_OF_BLUE))
                {
                    m_uiCancelShieldTimer = 5000;
                    std::list<HostileReference *> t_list = m_creature->getThreatManager().getThreatList();
                    for(std::list<HostileReference *>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
                    {
                        Unit *TargetedPlayer = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());  
                        if (TargetedPlayer && TargetedPlayer->GetTypeId() == TYPEID_PLAYER && TargetedPlayer->IsWithinDistInMap(Dragon, 10) && !TargetedPlayer->HasAura(AURA_BLUESHIELD))
                            TargetedPlayer->CastSpell(TargetedPlayer,AURA_BLUESHIELD,true);
                    }
                }
        }

		//stop blue shield
        if(m_uiCancelShieldTimer < diff)
        {
            std::list<HostileReference *> t_list = m_creature->getThreatManager().getThreatList();
            for(std::list<HostileReference *>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
            {
                Unit *ShieldedPlayer1 = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());
                if (ShieldedPlayer1 && ShieldedPlayer1->GetTypeId() == TYPEID_PLAYER && ShieldedPlayer1->HasAura(AURA_BLUESHIELD))
                {
                    ShieldedPlayer1->RemoveAurasDueToSpell(AURA_BLUESHIELD);
                } 
            }
            m_uiCancelShieldTimer = 300000;
        }else m_uiCancelShieldTimer -= diff;

        //Kalecgos and Anvena Event
        if((m_uiKalecgosAnvenaTimer < diff) && m_bIsAnvena)
        {
            switch(m_uiKalecgosAnvenaCount)
            {
                case 0:
                DoPlaySoundToSet(m_creature, SAY_KALECGOS_AWAKEN); m_uiKalecgosAnvenaTimer = 5000; break;
                case 1:
                DoPlaySoundToSet(m_creature, SAY_ANVEENA_IMPRISONED); m_uiKalecgosAnvenaTimer = 3000; break;
                case 2:
                DoPlaySoundToSet(m_creature, SAY_KALECGOS_LETGO); m_uiKalecgosAnvenaTimer = 6000; break;
                case 5:
                DoPlaySoundToSet(m_creature, SAY_ANVEENA_LOST); m_uiKalecgosAnvenaTimer = 4000; break;
                case 4:
                DoPlaySoundToSet(m_creature, SAY_KALECGOS_FOCUS); m_uiKalecgosAnvenaTimer = 8000; break;
                case 3:
                DoPlaySoundToSet(m_creature, SAY_ANVEENA_KALEC); m_uiKalecgosAnvenaTimer = 5000; break;
                case 6:
                DoPlaySoundToSet(m_creature, SAY_KALECGOS_FATE); m_uiKalecgosAnvenaTimer = 5000; break;
                case 7:
                DoPlaySoundToSet(m_creature, SAY_ANVEENA_GOODBYE); 
                m_creature->CastSpell(m_creature, SPELL_SACRIFICE_OF_ANVEENA, false);
                m_uiKalecgosAnvenaTimer = 5000;
                break;
                case 9:
                DoPlaySoundToSet(m_creature, SAY_KALECGOS_GOODBYE); ; m_bIsAnvena = false; break;
                case 8:
                DoPlaySoundToSet(m_creature, SAY_KALECGOS_ENCOURAGE); m_uiKalecgosAnvenaTimer = 14000; break;         
            }
            ++m_uiKalecgosAnvenaCount;
        } m_uiKalecgosAnvenaTimer -= diff;

        //Kalecgos Event working
        if((m_uiKalecgosTimer < diff) && !m_bIsKalecgosSpawned)
        {
            DoPlaySoundToSet(m_creature, SAY_KALECGOS_JOIN);
            Kalecgos = m_creature->SummonCreature(ID_KALECGOS, m_creature->GetPositionX()-25, m_creature->GetPositionY()-25, m_creature->GetPositionZ()+10, 0.686f, TEMPSUMMON_TIMED_DESPAWN, 600000);
            Kalecgos->setFaction(35);
            //Kalecgos need to start shhooting arcane bolt into Kiljaeden
            //Dragon->AI()->AttackStart(m_creature);
            m_bIsKalecgosSpawned = true;
        }m_uiKalecgosTimer -= diff;

        //Shield Orb At Start each phases working
       /* if(m_uiShieldOrbTimer < diff && !m_bPhase5)
        {
            uint8 l=1;
            if(m_bPhase3)
                l=2;
            if(m_bPhase4)
                l=3;
            for(uint8 k=0; k<l; ++k)
            {
                Creature* ShieldOrb = m_creature->SummonCreature(ID_SHIELDORB, m_creature->GetPositionX()+urand(1,15), m_creature->GetPositionY()+urand(1,15), m_creature->GetPositionZ()+15, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
                if(ShieldOrb)
                    ShieldOrb->AI()->AttackStart(m_creature->getVictim()); 
            }
            
            m_uiShieldOrbTimer = 50000; 
        }else m_uiShieldOrbTimer -= diff;*/

        //Sinister Reflects Attack Spell Timer
        if(m_uiSinnisterCastTimer < diff)
        {
            uint8 m_uiSinisterCount = 4;
            /*if(m_bPhase3)
                m_uiSinisterCount = 4;
            if(m_bPhase4)
                m_uiSinisterCount = 8;
            if(m_bPhase5)
                m_uiSinisterCount = 12;*/
            for(uint8 i=0; i<m_uiSinisterCount; ++i)
			{
                if(Unit* Sinister = Unit::GetUnit(*m_creature, m_uiSinisterGUID[i][0]))
				{
					if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
						Sinister->CastSpell(target, m_uiSinisterGUID[i][1], true);
				}
			}
            m_uiSinnisterCastTimer = 8000;
        }else m_uiSinnisterCastTimer -= diff;

        //Phase4
		//armageddon 
        if((m_uiAramageddonTimer < diff) && m_bPhase4)
        {
            uint8 h=3;
            if(m_bPhase5)
                h=5;
            if(!m_bPhase5 && m_bDarknessOfSoulsCasting)
                h=0;
            
            for(uint8 i=0; i<h; ++i)
            {
                if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
                    Creature* Armagedon = m_creature->SummonCreature(ID_ARMAGEDON, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 15000);
            }
            m_uiAramageddonTimer = 14000;
        }else m_uiAramageddonTimer -= diff;

        if((m_uiShadowSpikeEndsTimer < diff) && m_bShadowSpikeEnds && m_bPhase3)
        {
            if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
            {
                cShadowSpike = m_creature->SummonCreature(ID_SHADOWSPIKE, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 6000);
                cShadowSpike->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                cShadowSpike->setFaction(14);

                //target->CastSpell(target, SPELL_SHADOWSPIKE_EXP, false);
            }
            ++m_uiSpikesCount;
            if(m_uiSpikesCount > 9)
                m_bShadowSpikeEnds = false;
            m_uiShadowSpikeEndsTimer = 3000;
        }else m_uiShadowSpikeEndsTimer -= diff;

        if(m_bShadowSpikeEnds)
            return;

        if(m_uiDarknessExplosionTimer < diff && m_bDarknessOfSoulsCasting)
        {
            m_creature->CastSpell(m_creature->getVictim(), SPELL_DARKNESS_EXPLOSION, true);
            m_bDarknessOfSoulsCasting = false;
            m_uiDarknessExplosionTimer = 600000;
            m_uiDarknessOfSoulsTimer = 45000;
            if(m_bPhase5)
                m_uiDarknessOfSoulsTimer = 25000;
        }else m_uiDarknessExplosionTimer -= diff;

        if(m_bDarknessOfSoulsCasting)
            return;

		// darkness of a thousand souls from phase 3 on
        if(m_uiDarknessOfSoulsTimer < diff && m_bPhase3)
        {
            switch (rand()%3)
		        {
			        case 0: DoPlaySoundToSet(m_creature, SAY_KJ_DARKNESS1); break;
			        case 1: DoPlaySoundToSet(m_creature, SAY_KJ_DARKNESS2); break;
			        case 2: DoPlaySoundToSet(m_creature, SAY_KJ_DARKNESS3); break;
		        }
            m_creature->CastSpell(m_creature, SPELL_DARKNESS_OF_SOULS, true);
            m_bDarknessOfSoulsCasting = true;
            m_uiDarknessExplosionTimer = 8500;
        }else m_uiDarknessOfSoulsTimer -= diff;

        // After Each Phase Dragons Are Spawned
        if((m_uiOrbTimer < diff) && !m_bBoolOrb)
        {
            for(uint8 i=0; i<4; ++i)
                DragonGUID[i] = 0;

            switch (rand()%4)
		        {
			        case 0: DoPlaySoundToSet(m_creature, SAY_KALEC_ORB_READY1); break;
			        case 1: DoPlaySoundToSet(m_creature, SAY_KALEC_ORB_READY2); break;
			        case 2: DoPlaySoundToSet(m_creature, SAY_KALEC_ORB_READY3); break;
                    case 3: DoPlaySoundToSet(m_creature, SAY_KALEC_ORB_READY4); break;
		        }
            uint8 m_uiMaxDragons = 1;
            if(m_bPhase5)
                m_uiMaxDragons = 4;
            for(uint8 i=0; i<m_uiMaxDragons; ++i)
            {
                Creature* Dragon = m_creature->SummonCreature(ID_DRAGON, m_creature->GetPositionX()+urand(5,20), m_creature->GetPositionY()+urand(5,20), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 20000);
                DragonGUID[i] = Dragon->GetGUID();
            }
            m_bBoolOrb = true;
        }else m_uiOrbTimer -= diff;

        //FireBloom Damage WorkArround
        if (m_uiFireBloomCheck < diff)
        {
            if(m_uiFireBloomCount < 10)
                for(uint8 i=0; i<5; ++i)
                {
                    if(Unit* FireTarget = Unit::GetUnit(*m_creature, m_uiFireBloomTarget[i]))
                        FireTarget->CastSpell(FireTarget, SPELL_FIREBLOOM_EFF, true);
                }
            ++m_uiFireBloomCount;
            m_uiFireBloomCheck = 2000;
        }else m_uiFireBloomCheck -= diff;

        //Phase 3 init
        if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) <= 85) && !m_bPhase3)
        {      
            DoPlaySoundToSet(m_creature, SAY_KJ_PHASE3);
            if(Unit* victim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) 
                if (victim && (victim->GetTypeId() == TYPEID_PLAYER))
                    Sinister(((Player*)victim),0,4);
			m_creature->MonsterYell("entering phase 3",LANG_UNIVERSAL,0);

            m_uiSinnisterCastTimer     = 10000;
            m_uiShadowSpikeTimer       = 30000;
            m_uiFlameDartTimer         = 40000;
            m_uiDarknessOfSoulsTimer   = 45000;
            m_bShadowSpikeEnds         = false;
            m_bDarknessOfSoulsCasting  = false;
            m_bPhase3 = true;
            //DragonsTimer
            m_uiOrbTimer = 35000;
            m_bBoolOrb = false;
        }

		//phase 4 init
        if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) <= 55) && !m_bPhase4)
        {
            DoPlaySoundToSet(m_creature, SAY_KJ_PHASE4);
            if(Unit* victim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) 
                if (victim && (victim->GetTypeId() == TYPEID_PLAYER))
                    Sinister(((Player*)victim),4,8);
			m_creature->MonsterYell("entering phase 4",LANG_UNIVERSAL,0);

            m_uiAramageddonTimer       = 2000;  //100% ok
            m_bPhase4 = true;
            m_uiDarknessOfSoulsTimer   = 45000;
            //DragonsTimer
            m_uiOrbTimer = 35000;
            m_bBoolOrb = false;
        }

		//phase 5 init
        if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) <= 25) && !m_bPhase5)
        {
            DoPlaySoundToSet(m_creature, SAY_KJ_PHASE5);
            if(Unit* victim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) 
                if (victim && (victim->GetTypeId() == TYPEID_PLAYER))
                    Sinister(((Player*)victim),8,12);
			m_creature->MonsterYell("entering phase 5",LANG_UNIVERSAL,0);
            m_uiShadowSpikeTimer = 1000;
            m_uiDarknessOfSoulsTimer   = 45000;
            m_bPhase5 = true;
            //DragonsTimer
            m_uiOrbTimer = 35000;
            m_bBoolOrb = false;
            //Kalecgos and Anvena Event
            m_uiKalecgosAnvenaTimer = 20000;
            m_bIsAnvena = true;
            m_uiKalecgosAnvenaCount = 0;

            Creature* Anveena = m_creature->SummonCreature(ID_ANVEENA, m_creature->GetPositionX()+urand(20,30), m_creature->GetPositionY()+urand(20,30), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 120000);
            Anveena->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
            Anveena->setFaction(35);
        }

        //spells used from phase 3 on
        if(m_bPhase3)
        {
			if(m_uiShadowSpikeTimer < diff)
            {
                DoCast(m_creature->getVictim(), SPELL_SHADOWSPIKE);

                m_bShadowSpikeEnds         = true;
                m_uiShadowSpikeEndsTimer    = 500;
                m_uiSpikesCount             = 0;
                m_uiShadowSpikeTimer        = 90000;
            }else m_uiShadowSpikeTimer -= diff;

			//flame dart
            if(m_uiFlameDartTimer < diff )
            {
                DoCast(m_creature->getVictim(), SPELL_FLAMEDARTS);
                m_uiFlameDartTimer = 33000;
            }else m_uiFlameDartTimer -= diff;
        }

        //Phase2
		// legion lightning all phases
        if(m_uiLegionLightingTimer < diff)
        {
            DoCast(m_creature->getVictim(), SPELL_LEGION_LIGHTING);
            m_uiLegionLightingTimer = 11000;
        }else m_uiLegionLightingTimer -= diff;

		// fire bloom all phases
        if(m_uiFireBloomTimer < diff)
        {
            for(uint8 i=0; i<5; ++i)
            {
                Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);
                m_uiFireBloomTarget[i] = target->GetGUID();
                m_uiFireBloomCount = 0;
                //DoCast(target, SPELL_FIREBLOOM, true);
            }
            m_uiFireBloomTimer = 25000;
        }else m_uiFireBloomTimer -= diff;

		// soul flay all phases
        if(m_uiSoulFlayTimer < diff)
        {
            DoCast(m_creature->getVictim(), SPELL_SOULFLAY);
            m_uiSoulFlayTimer = 7000;
        }else m_uiSoulFlayTimer -= diff;

        DoMeleeAttackIfReady();
    }
Example #9
0
void WorldSession::HandlePetAction(WorldPacket& recv_data)
{
    ObjectGuid petGuid;
    uint32 data;
    ObjectGuid targetGuid;
    recv_data >> petGuid;
    recv_data >> data;
    recv_data >> targetGuid;

    uint32 spellid = UNIT_ACTION_BUTTON_ACTION(data);
    uint8 flag = UNIT_ACTION_BUTTON_TYPE(data);             // delete = 0x07 CastSpell = C1

    DETAIL_LOG("HandlePetAction: %s flag is %u, spellid is %u, target %s.", petGuid.GetString().c_str(), uint32(flag), spellid, targetGuid.GetString().c_str());

    // used also for charmed creature/player
    Unit* petUnit = _player->GetMap()->GetUnit(petGuid);
    if (!petUnit)
    {
        sLog.outError("HandlePetAction: %s not exist.", petGuid.GetString().c_str());
        return;
    }

    if (_player->GetObjectGuid() != petUnit->GetMasterGuid())
    {
        sLog.outError("HandlePetAction: %s isn't controlled by %s.", petGuid.GetString().c_str(), _player->GetGuidStr().c_str());
        return;
    }

    if (!petUnit->isAlive())
        return;

    CharmInfo* charmInfo = petUnit->GetCharmInfo();
    if (!charmInfo)
    {
        sLog.outError("WorldSession::HandlePetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", petUnit->GetGUIDLow(), petUnit->GetTypeId());
        return;
    }

    Pet* pet = nullptr;
    Creature* creature = nullptr;

    if (petUnit->GetTypeId() == TYPEID_UNIT)
    {
        creature = static_cast<Creature*>(petUnit);

        if (creature->IsPet())
        {
            pet = static_cast<Pet*>(petUnit);

            if (pet->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)
                return;
        }
    }

    if (!pet)
    {
        if (petUnit->hasUnitState(UNIT_STAT_POSSESSED))
        {
            // possess case
            if (flag != uint8(ACT_COMMAND))
            {
                sLog.outError("PetHAndler: unknown PET flag Action %i and spellid %i. For possessed %s", uint32(flag), spellid, petUnit->GetGuidStr().c_str());
                return;
            }

            switch (spellid)
            {
                case COMMAND_STAY:
                case COMMAND_FOLLOW:
                    charmInfo->SetCommandState(CommandStates(spellid));
                    break;
                case COMMAND_ATTACK:
                {
                    Unit* targetUnit = targetGuid ? _player->GetMap()->GetUnit(targetGuid) : nullptr;

                    if (targetUnit && targetUnit != petUnit && petUnit->CanAttack(targetUnit))
                    {
                        // This is true if pet has no target or has target but targets differs.
                        if (petUnit->getVictim() != targetUnit)
                            petUnit->Attack(targetUnit, true);
                    }
                    break;
                }
                case COMMAND_DISMISS:
                    _player->BreakCharmOutgoing(petUnit);
                    break;
                default:
                    sLog.outError("PetHandler: Not allowed action %i and spellid %i. Pet %s owner is %s", uint32(flag), spellid, petUnit->GetGuidStr().c_str(), _player->GetGuidStr().c_str());
                    break;
            }
        }

        if (!petUnit->HasCharmer())
            return;
    }

    switch (flag)
    {
        case ACT_COMMAND:                                   // 0x07
            switch (spellid)
            {
                case COMMAND_STAY:                          // flat=1792  // STAY
                {
                    if (!petUnit->hasUnitState(UNIT_STAT_POSSESSED))
                    {
                        petUnit->StopMoving();
                        petUnit->GetMotionMaster()->Clear();
                    }
                    petUnit->AttackStop(true, true);
                    charmInfo->SetCommandState(COMMAND_STAY);
                    break;
                }
                case COMMAND_FOLLOW:                        // spellid=1792  // FOLLOW
                {
                    if (!petUnit->hasUnitState(UNIT_STAT_POSSESSED))
                    {
                        petUnit->StopMoving();
                        petUnit->GetMotionMaster()->Clear();
                        charmInfo->SetIsRetreating(true);
                    }
                    petUnit->AttackStop(true, true);
                    charmInfo->SetCommandState(COMMAND_FOLLOW);
                    break;
                }
                case COMMAND_ATTACK:                        // spellid=1792  // ATTACK
                {
                    charmInfo->SetIsRetreating();
                    charmInfo->SetSpellOpener();

                    Unit* targetUnit = targetGuid ? _player->GetMap()->GetUnit(targetGuid) : nullptr;

                    if (targetUnit && targetUnit != petUnit && petUnit->CanAttack(targetUnit) && targetUnit->isInAccessablePlaceFor((Creature*)petUnit))
                    {
                        // This is true if pet has no target or has target but targets differs.
                        if (petUnit->getVictim() != targetUnit)
                        {
                            petUnit->AttackStop();
                            if (!petUnit->hasUnitState(UNIT_STAT_POSSESSED))
                            {
                                petUnit->GetMotionMaster()->Clear();

                                petUnit->AI()->AttackStart(targetUnit);

                                if (pet)
                                {
                                    // 10% chance to play special warlock pet attack talk, else growl
                                    if (pet->getPetType() == SUMMON_PET && roll_chance_i(10))
                                        pet->SendPetTalk((uint32)PET_TALK_ATTACK);

                                    pet->SendPetAIReaction();
                                }
                            }
                            else
                                petUnit->Attack(targetUnit, true);
                        }
                    }
                    break;
                }
                case COMMAND_DISMISS:                       // dismiss permanent pet, remove temporary pet, uncharm unit
                {
                    if (pet)
                    {
                        pet->PlayDismissSound();
                        // No action for Hunter pets, Hunters must use their Dismiss Pet spell
                        if (pet->getPetType() != HUNTER_PET)
                            pet->ForcedDespawn();
                    }
                    else
                    {
                        // dismissing a summoned pet is like killing them (this prevents returning a soulshard...)
                        if (creature && creature->IsTemporarySummon())
                            creature->ForcedDespawn();
                        else
                            _player->BreakCharmOutgoing(petUnit);
                    }

                    charmInfo->SetStayPosition();
                    break;
                }
                default:
                    sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid);
            }
            break;
        case ACT_REACTION:                                  // 0x6
            switch (spellid)
            {
                case REACT_PASSIVE:                         // passive
                {
                    petUnit->AttackStop(true, true);
                    charmInfo->SetSpellOpener();
                }
                case REACT_DEFENSIVE:                       // recovery
                case REACT_AGGRESSIVE:                      // activete
                {
                    petUnit->AI()->SetReactState(ReactStates(spellid));
                    break;
                }
            }
            break;
        case ACT_DISABLED:                                  // 0x81    spell (disabled), ignore
        case ACT_PASSIVE:                                   // 0x01
        case ACT_ENABLED:                                   // 0xC1    spell
        {
            charmInfo->SetIsRetreating();
            charmInfo->SetSpellOpener();

            Unit* unit_target = targetGuid ? _player->GetMap()->GetUnit(targetGuid) : nullptr;

            // do not cast unknown spells
            SpellEntry const* spellInfo = sSpellTemplate.LookupEntry<SpellEntry>(spellid);
            if (!spellInfo)
            {
                sLog.outError("WORLD: unknown PET spell id %i", spellid);
                return;
            }

            // do not cast not learned spells
            if (IsPassiveSpell(spellInfo) || !petUnit->HasSpell(spellid))
                return;

            if (!petUnit->IsSpellReady(*spellInfo))
                return;

            for (unsigned int i : spellInfo->EffectImplicitTargetA)
            {
                if (i == TARGET_ENUM_UNITS_ENEMY_AOE_AT_SRC_LOC
                        || i == TARGET_ENUM_UNITS_ENEMY_AOE_AT_DEST_LOC
                        || i == TARGET_ENUM_UNITS_ENEMY_AOE_AT_DYNOBJ_LOC)
                    return;
            }

            petUnit->clearUnitState(UNIT_STAT_MOVING);

            uint32 flags = TRIGGERED_NONE;
            if (!petUnit->hasUnitState(UNIT_STAT_POSSESSED))
                flags |= TRIGGERED_PET_CAST;

            Spell* spell = new Spell(petUnit, spellInfo, flags);

            SpellCastResult result = spell->CheckPetCast(unit_target);

            const SpellRangeEntry* sRange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex);

            if (unit_target && !(petUnit->IsWithinDistInMap(unit_target, sRange->maxRange) && petUnit->IsWithinLOSInMap(unit_target))
                    && petUnit->CanAttackNow(unit_target))
            {
                charmInfo->SetSpellOpener(spellid, sRange->minRange, sRange->maxRange);
                spell->finish(false);
                delete spell;

                petUnit->AttackStop();

                if (!petUnit->hasUnitState(UNIT_STAT_POSSESSED))
                {
                    petUnit->GetMotionMaster()->Clear();

                    petUnit->AI()->AttackStart(unit_target);
                    // 10% chance to play special warlock pet attack talk, else growl
                    if (pet && pet->getPetType() == SUMMON_PET && pet != unit_target && roll_chance_i(10))
                        petUnit->SendPetTalk((uint32)PET_TALK_ATTACK);

                    petUnit->SendPetAIReaction();
                }
                else
                    petUnit->Attack(unit_target, true);

                return;
            }

            // auto turn to target unless possessed
            if (result == SPELL_FAILED_UNIT_NOT_INFRONT && !petUnit->hasUnitState(UNIT_STAT_POSSESSED))
            {
                if (unit_target)
                {
                    petUnit->SetInFront(unit_target);
                    if (unit_target->GetTypeId() == TYPEID_PLAYER)
                        petUnit->SendCreateUpdateToPlayer((Player*)unit_target);
                }
                else if (Unit* unit_target2 = spell->m_targets.getUnitTarget())
                {
                    petUnit->SetInFront(unit_target2);
                    if (unit_target2->GetTypeId() == TYPEID_PLAYER)
                        petUnit->SendCreateUpdateToPlayer((Player*)unit_target2);
                }
                if (Unit* powner = petUnit->GetMaster())
                    if (powner->GetTypeId() == TYPEID_PLAYER)
                        petUnit->SendCreateUpdateToPlayer((Player*)powner);
                result = SPELL_CAST_OK;
            }

            if (result == SPELL_CAST_OK)
            {
                charmInfo->SetSpellOpener();
                spell->SpellStart(&(spell->m_targets));
            }
            else
            {
                if (creature && creature->IsSpellReady(*spellInfo))
                    GetPlayer()->SendClearCooldown(spellid, petUnit);

                charmInfo->SetSpellOpener();
                spell->finish(false);
                delete spell;
            }
            break;
        }
        default:
            sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid);
    }
}
Example #10
0
void PetAI::UpdateAI(const uint32 diff)
{
    if (!m_creature->isAlive())
        return;

    Unit* owner = m_creature->GetCharmerOrOwner();
    Unit* victim = m_creature->getVictim();

    if (m_updateAlliesTimer <= diff)
        // UpdateAllies self set update timer
        UpdateAllies();
    else
        m_updateAlliesTimer -= diff;

    if (inCombat && (!victim || (m_creature->IsPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)))
        _stopAttack();

    if (((Pet*)m_creature)->GetIsRetreating())
    {
        if (!owner->_IsWithinDist(m_creature, (PET_FOLLOW_DIST * 2), true))
        {
            if (!m_creature->hasUnitState(UNIT_STAT_FOLLOW))
                m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);

            return;
        }
        else
           ((Pet*)m_creature)->SetIsRetreating();
    }
    else if (((Pet*)m_creature)->GetSpellOpener() != 0) // have opener stored
    {
        uint32 minRange = ((Pet*)m_creature)->GetSpellOpenerMinRange();

        if (!(victim = m_creature->getVictim())
            || (minRange != 0 && m_creature->IsWithinDistInMap(victim, minRange)))
            ((Pet*)m_creature)->SetSpellOpener();
        else if (m_creature->IsWithinDistInMap(victim, ((Pet*)m_creature)->GetSpellOpenerMaxRange()) && m_creature->IsWithinLOSInMap(victim))
        {
            // stop moving
            m_creature->clearUnitState(UNIT_STAT_MOVING);

            // auto turn to target
            m_creature->SetInFront(victim);

            if (victim->GetTypeId() == TYPEID_PLAYER)
                m_creature->SendCreateUpdateToPlayer((Player*)victim);

            if (owner->GetTypeId() == TYPEID_PLAYER)
                m_creature->SendCreateUpdateToPlayer((Player*)owner);

            uint32 spell_id = ((Pet*)m_creature)->GetSpellOpener();
            SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);

            Spell* spell = new Spell(m_creature, spellInfo, false);

            SpellCastResult result = spell->CheckPetCast(victim);

            if (result == SPELL_CAST_OK)
            {
                m_creature->AddCreatureSpellCooldown(spell_id);

                spell->SpellStart(&(spell->m_targets));
            }
            else
                delete spell;

            ((Pet*)m_creature)->SetSpellOpener();
        }

        else
            return;
    }
    // Autocast (casted only in combat or persistent spells in any state)
    else if (!m_creature->IsNonMeleeSpellCasted(false))
    {
        typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
        TargetSpellList targetSpellStore;

        for (uint8 i = 0; i < m_creature->GetPetAutoSpellSize(); ++i)
        {
            uint32 spellID = m_creature->GetPetAutoSpellOnPos(i);
            if (!spellID)
                continue;

            SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellID);
            if (!spellInfo)
                continue;

            if (m_creature->GetCharmInfo() && m_creature->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
                continue;

            // ignore some combinations of combat state and combat/noncombat spells
            if (!inCombat)
            {
                // ignore attacking spells, and allow only self/around spells
                if (!IsPositiveSpell(spellInfo->Id))
                    continue;

                // non combat spells allowed
                // only pet spells have IsNonCombatSpell and not fit this reqs:
                // Consume Shadows, Lesser Invisibility, so ignore checks for its
                if (!IsNonCombatSpell(spellInfo))
                {
                    int32 duration = GetSpellDuration(spellInfo);
                    int32 cooldown = GetSpellRecoveryTime(spellInfo);

                    // allow only spell not on cooldown
                    if (cooldown != 0 && duration < cooldown)
                        continue;

                    // not allow instant kill autocasts as full health cost
                    if (IsSpellHaveEffect(spellInfo, SPELL_EFFECT_INSTAKILL))
                        continue;
                }
            }
            // just ignore non-combat spells
            else if (IsNonCombatSpell(spellInfo))
                continue;

            Spell* spell = new Spell(m_creature, spellInfo, false);

            if (inCombat && !m_creature->hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(m_creature->getVictim()))
            {
                targetSpellStore.push_back(TargetSpellList::value_type(m_creature->getVictim(), spell));
                continue;
            }
            else
            {
                bool spellUsed = false;
                for (GuidSet::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
                {
                    Unit* Target = m_creature->GetMap()->GetUnit(*tar);

                    // only buff targets that are in combat, unless the spell can only be cast while out of combat
                    if (!Target)
                        continue;

                    if (spell->CanAutoCast(Target))
                    {
                        targetSpellStore.push_back(TargetSpellList::value_type(Target, spell));
                        spellUsed = true;
                        break;
                    }
                }
                if (!spellUsed)
                    delete spell;
            }
        }

        // found units to cast on to
        if (!targetSpellStore.empty())
        {
            uint32 index = urand(0, targetSpellStore.size() - 1);

            Spell* spell  = targetSpellStore[index].second;
            Unit*  target = targetSpellStore[index].first;

            targetSpellStore.erase(targetSpellStore.begin() + index);

            SpellCastTargets targets;
            targets.setUnitTarget(target);

            if (!m_creature->HasInArc(M_PI_F, target))
            {
                m_creature->SetInFront(target);
                if (target->GetTypeId() == TYPEID_PLAYER)
                    m_creature->SendCreateUpdateToPlayer((Player*)target);

                if (owner && owner->GetTypeId() == TYPEID_PLAYER)
                    m_creature->SendCreateUpdateToPlayer((Player*)owner);
            }

            m_creature->AddCreatureSpellCooldown(spell->m_spellInfo->Id);
            if (m_creature->IsPet())
                ((Pet*)m_creature)->CheckLearning(spell->m_spellInfo->Id);

            spell->SpellStart(&targets);
        }

        // deleted cached Spell objects
        for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
            delete itr->second;
    }
    else if (m_creature->hasUnitState(UNIT_STAT_FOLLOW_MOVE))
        m_creature->InterruptNonMeleeSpells(false);

    if (victim = m_creature->getVictim())
    {
        // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.
        if (_needToStop())
        {
            DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "PetAI (guid = %u) is stopping attack.", m_creature->GetGUIDLow());
            _stopAttack();
            return;
        }

        // required to be stopped cases
        if (m_creature->IsStopped() && m_creature->IsNonMeleeSpellCasted(false))
        {
            if (m_creature->hasUnitState(UNIT_STAT_FOLLOW_MOVE))
                    m_creature->InterruptNonMeleeSpells(false);
        }

        else if (m_creature->CanReachWithMeleeAttack(victim))
        {
            if (DoMeleeAttackIfReady())
                // if pet misses its target, it will also be the first in threat list
                victim->AddThreat(m_creature);
            else
                AttackStart(victim);
        }
    }
    else if (owner && m_creature->GetCharmInfo())
    {
        if (owner->isInCombat() && !(m_creature->GetCharmInfo()->HasReactState(REACT_PASSIVE) || m_creature->GetCharmInfo()->HasCommandState(COMMAND_STAY)))
        {
            AttackStart(owner->getAttackerForHelper());
        }
        else if (m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
        {
            // The distance is to prevent the pet from running around to reach the owners back when  walking towards it
            //  and the reason for increasing it more than the follow distance is to prevent the same thing
            // from happening when the owner turns and twists (as this increases the distance between them)
            if (!m_creature->hasUnitState(UNIT_STAT_FOLLOW) && !owner->IsWithinDistInMap(m_creature, (PET_FOLLOW_DIST * 2)))
                m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
            // This is to stop the pet from following you when you're close to each other, to support the above condition.
            else if (m_creature->hasUnitState(UNIT_STAT_FOLLOW))
            {
                m_creature->GetMotionMaster()->Clear(false);
                m_creature->GetMotionMaster()->MoveIdle();
            }
        }
    }
}
Example #11
0
    void UpdateAI(const uint32 uiDiff)
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        if(m_uiIntroTimer < uiDiff)
        {
            if(m_bIsIntroNow)
            {
                m_creature->StopMoving();
                m_creature->GetMotionMaster()->Clear();
                m_creature->GetMotionMaster()->MoveIdle();

                switch(m_uiIntroCount)
                {
                    case 0:
                        DoPlaySoundToSet(m_creature, SOUND_MADR_ICE_BARRIER);
                        m_uiIntroTimer = 6000; break;
                    case 1:
                        DoPlaySoundToSet(m_creature, SOUND_MADR_INTRO);
                        m_uiIntroTimer = 5000; break;
                    case 2:
                        DoPlaySoundToSet(m_creature, SOUND_INTRO);
                        m_uiIntroTimer = 6000; break;
                    case 3:
                        DoPlaySoundToSet(m_creature, SOUND_MADR_ICE_BLOCK);
                        m_uiIntroTimer = 4000; break;
                    case 4:
                        DoPlaySoundToSet(m_creature, SOUND_INTRO_BREAK_ICE);
                        m_uiIntroTimer = 5000; break;
                    case 5:
                        DoPlaySoundToSet(m_creature, SOUND_MADR_TRAP);
                        m_uiIntroTimer = 5000; break;
                    case 6:
                        DoPlaySoundToSet(m_creature, SOUND_INTRO_CHARGE);
                        m_uiIntroTimer = 5000; break;
                    case 7:
                        DoPlaySoundToSet(m_creature, SOUND_MADR_DEATH);
                        m_uiIntroTimer = 5000; break;
                    case 8:
                        DoPlaySoundToSet(m_creature, SOUND_INTRO_KILL_MADRIGOSA);
                        m_uiIntroTimer = 6000; break;
                    case 9:
                        DoPlaySoundToSet(m_creature, SOUND_INTRO_TAUNT);
                        m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
                        m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                        m_uiBerserkTimer = 360000;
                        m_bIsIntroNow = false; break;
                }
                ++m_uiIntroCount;
            }
        }else m_uiIntroTimer -= uiDiff;

        if(m_bIsIntroNow)
            return;

        if (m_uiBurnCheckTimer < uiDiff)
        {
            std::list<HostileReference *> t_list = m_creature->getThreatManager().getThreatList();
            for(std::list<HostileReference *>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
            {
                Unit *BurnedPlayer = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());
                if (BurnedPlayer && BurnedPlayer->GetTypeId() == TYPEID_PLAYER && BurnedPlayer->HasAura(SPELL_BURN_AURA))
                {
                    std::list<HostileReference *> t_list = m_creature->getThreatManager().getThreatList();
                    for(std::list<HostileReference *>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
                    {
                        Unit *TargetedPlayer = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());  
                        if (TargetedPlayer && TargetedPlayer->GetTypeId() == TYPEID_PLAYER && TargetedPlayer->IsWithinDistInMap(BurnedPlayer, 6) && !TargetedPlayer->HasAura(SPELL_BURN_AURA))
                            TargetedPlayer->CastSpell(TargetedPlayer,SPELL_BURN_AURA,true);
                    }
                }
            }          
            m_uiBurnCheckTimer = 1000;        
        }else m_uiBurnCheckTimer -= uiDiff;

        if (m_uiLoveTimer < uiDiff)
        {
            switch(urand(0, 2))
            {
                case 0: DoScriptText(YELL_LOVE1, m_creature); break;
                case 1: DoScriptText(YELL_LOVE2, m_creature); break;
                case 2: DoScriptText(YELL_LOVE3, m_creature); break;
            }
            m_uiLoveTimer = urand(15000, 23000);
        }
        else
            m_uiLoveTimer -= uiDiff;

        if (m_uiSlashTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->getVictim())
                DoCast(pTarget,SPELL_METEOR_SLASH);
            m_uiSlashTimer = 11000;
        }else m_uiSlashTimer -= uiDiff;

        if (m_uiStompTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->getVictim())
            {
                DoCast(pTarget,SPELL_STOMP);

                if (pTarget->HasAura(SPELL_BURN_AURA,0))
                   pTarget->RemoveAurasDueToSpell(SPELL_BURN_AURA);
            }
            m_uiStompTimer = 30000;
        }
        else
            m_uiStompTimer -= uiDiff;

        if (m_uiBurnTimer < uiDiff)
        {
            if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
            {
                DoCast(target,SPELL_BURN);
                target->CastSpell(target,SPELL_BURN_AURA, true);
            }
            m_uiBurnTimer = 60000;
        }
        else m_uiBurnTimer -= uiDiff;

        if (m_uiBerserkTimer < uiDiff)
        {
            DoScriptText(YELL_BERSERK, m_creature);
            DoCast(m_creature,SPELL_BERSERK);
            m_uiBerserkTimer = 20000;
        }
        else
            m_uiBerserkTimer -= uiDiff;

        DoMeleeAttackIfReady();
    }
void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T &owner)
{
    if (!i_target.isValid() || !i_target->IsInWorld())
        return;

    if (owner.hasUnitState(UNIT_STAT_NOT_MOVE))
        return;

    if (owner.GetTypeId() == TYPEID_PLAYER && ((Player*)&owner)->IsBot())
    {
        Unit* bot = (Unit*)&owner;
        float x, y, z;

        if (i_target.getTarget()==bot)
        {
            // prevent redundant micro-movement for bots, other followers.
            if (i_offset && bot->IsWithinDistInMap(bot, i_x, i_y, i_z, 2*i_offset))
            {
                if (!owner.movespline->Finalized())
                    return;

                owner.GetPosition(x, y, z);
            }
            else
            {
                x = i_x; y = i_y; z = i_z;
            }
        }
        else
        {
            // prevent redundant micro-movement for bots, other followers.
            if (i_offset && !i_target->GetTransport() && i_target->IsWithinDistInMap(&owner,2*i_offset))
            {
                if (!owner.movespline->Finalized())
                    return;

                owner.GetPosition(x, y, z);
            }
            else if (!i_offset)
            {
                // to nearest contact position
                i_target->GetContactPoint( &owner, x, y, z );
            }
            else
            {
                // to at i_offset distance from target and i_angle from target facing
                i_target->GetClosePoint(x, y, z, owner.GetObjectBoundingRadius(), i_offset, i_angle, &owner);
            }
        }

        /*bool forceDest = false;
        // allow bots following their leader to cheat while generating paths (bypass mmaps)
        if(owner.GetTypeId() == TYPEID_PLAYER && ((Player*)&owner)->IsBot()
            && owner.hasUnitState(UNIT_STAT_FOLLOW))
            forceDest = true;*/

        if(!i_path)
            i_path = new PathInfo(&owner);

        /*// allow pets following their master to cheat while generating paths
        bool forceDest = (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->IsPet()
                            && owner.hasUnitState(UNIT_STAT_FOLLOW));*/

        i_path->calculate(x, y, z, false, false);
        if(i_path->getPathType() & PATHFIND_NOPATH)
        {
            i_path->calculate(x, y, z, false, true);
            if(i_path->getPathType() & PATHFIND_NOPATH)
            {
                ((Player*)&owner)->TeleportTo(((Player*)&owner)->GetMapId(), x, y, z, 0.0f);
                return;
            }
        }

        D::_addUnitStateMove(owner);
        i_targetReached = false;
        i_recalculateTravel = false;

        Movement::MoveSplineInit init(owner);
        init.MovebyPath(i_path->getPath());
        init.SetWalk(((D*)this)->EnableWalking());
        init.Launch();
    }
    else
    {
        float x, y, z;

        // prevent redundant micro-movement for pets, other followers.
        if (i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset))
        {
            if (!owner.movespline->Finalized())
                return;

            owner.GetPosition(x, y, z);
        }
        else if (!i_offset)
        {
            // to nearest contact position
            i_target->GetContactPoint( &owner, x, y, z );
        }
        else
        {
            // to at i_offset distance from target and i_angle from target facing
            i_target->GetClosePoint(x, y, z, owner.GetObjectBoundingRadius(), i_offset, i_angle, &owner);
        }

        /*
            We MUST not check the distance difference and avoid setting the new location for smaller distances.
            By that we risk having far too many GetContactPoint() calls freezing the whole system.
            In TargetedMovementGenerator<T>::Update() we check the distance to the target and at
            some range we calculate a new position. The calculation takes some processor cycles due to vmaps.
            If the distance to the target it too large to ignore,
            but the distance to the new contact point is short enough to be ignored,
            we will calculate a new contact point each update loop, but will never move to it.
            The system will freeze.
            ralf

            //We don't update Mob Movement, if the difference between New destination and last destination is < BothObjectSize
            float  bothObjectSize = i_target->GetObjectBoundingRadius() + owner.GetObjectBoundingRadius() + CONTACT_DISTANCE;
            if( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize )
                return;
        */

        if(!i_path)
            i_path = new PathInfo(&owner);

        // allow pets following their master to cheat while generating paths
        bool forceDest = (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->IsPet()
                            && owner.hasUnitState(UNIT_STAT_FOLLOW));
        i_path->calculate(x, y, z, false, forceDest);
        if(i_path->getPathType() & PATHFIND_NOPATH)
            return;

        D::_addUnitStateMove(owner);
        i_targetReached = false;
        i_recalculateTravel = false;

        Movement::MoveSplineInit init(owner);
        init.MovebyPath(i_path->getPath());
        init.SetWalk(((D*)this)->EnableWalking());
        init.Launch();
    }
}
	void UpdateAI(const uint32 diff)
    {       
		
		// return since we have no target
        if(!m_creature->SelectHostileTarget() || !m_creature->getVictim())
           return;
		
        if (m_creature->HasAura(SPELL_BANISH))
        {
            if (pInstance && pInstance->GetData(DATA_SACROLASH_EVENT) == DONE)
            {
                m_creature->SetVisibility(VISIBILITY_ON);
                m_creature->RemoveAurasDueToSpell(SPELL_BANISH);
            }

            if (pInstance && pInstance->GetData(DATA_EREDAR_TWINS_EVENT) == NOT_STARTED)
            {
                m_creature->SetVisibility(VISIBILITY_ON);
                m_creature->RemoveAurasDueToSpell(SPELL_BANISH);
                ((boss_alythessAI*)m_creature->AI())->Reset();
                m_creature->AI()->EnterEvadeMode();
            }
            return;
        }

        /* Banish at 1% hp working */
        if (((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) <= 1) && !m_bIsBanished)
        {
            if (pInstance && pInstance->GetData(DATA_SACROLASH_EVENT) != DONE)
            {
                pInstance->SetData(DATA_ALYSTHESS_EVENT, DONE);
                DoCast(m_creature, SPELL_BANISH, true);
                m_creature->SetVisibility(VISIBILITY_OFF);
            }
            m_bIsBanished = true;
        }

        if(m_uiConfCount = 10)
        {
            if(Unit* pPlayer = m_creature->GetMap()->GetUnit(m_uiConfTargetGUID))
                pPlayer->RemoveAurasDueToSpell(AURA_CONF,0);
            ++m_uiConfCount;
        }

        if(m_uiConfCount < 10)
        {
            if(m_uiConfTimer < diff)
            {
                if(Unit* pPlayer = m_creature->GetMap()->GetUnit(m_uiConfTargetGUID))
                {
                    pPlayer->CastSpell(pPlayer, SPELL_CONFLAGRATION_DEV, true);

                    std::list<HostileReference *> t_list = m_creature->getThreatManager().getThreatList();
                    for(std::list<HostileReference *>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
                    {
                        Unit *BurnedPlayer = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid());
                        if (BurnedPlayer && BurnedPlayer->GetTypeId() == TYPEID_PLAYER && BurnedPlayer->IsWithinDistInMap(pPlayer, 8))
                        {
                            BurnedPlayer->CastSpell(BurnedPlayer, SPELL_CONFLAGRATION_DEV, true);
                        }
                    }    
                }
                ++m_uiConfCount;
                m_uiConfTimer = 1000;        
            }else m_uiConfTimer -= diff;
        }

		// does alysthes stand and cast spells, after someone is out of range she follows victim
		if(Unit *who = m_creature->getVictim())
        {
		    if(who && who->IsInRange(m_creature, 0.0f, 15.0f, false))
			    m_creature->StopMoving();
            else 
			    m_creature->CanFreeMove();
        }

        // enrage
        if(m_uiEnrageTimer < diff && !m_bIsEnraged)
        {
            DoScriptText(YELL_TWINS_ENRAGE, m_creature);
            DoCast(m_creature, SPELL_TWINS_ENRAGE);
            m_bIsEnraged = true;
        }else m_uiEnrageTimer -= diff;
		
		// 100%
        if(m_uiPyrogenicsTimer < diff)
        {
            DoCast(m_creature, SPELL_PYROGENICS);
            m_uiPyrogenicsTimer = 35000;
        }else m_uiPyrogenicsTimer -= diff;
		
		// 100%
		if(m_uiFlameTouchedTimer < diff)
        {
			if (Unit* victim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
                victim->CastSpell(victim, SPELL_FLAME_TOUCHED, true);
            m_uiFlameTouchedTimer = 30000;
        }else m_uiFlameTouchedTimer -= diff;
		
		// in progress
        if(m_uiConflagrationTimer < diff)
        {
            m_uiConfTargetGUID = 0;
			if (Unit *victim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
            {
                m_uiConfTargetGUID = victim->GetGUID();
                victim->CastSpell(victim, AURA_CONF, true);
                victim->CastSpell(victim, SPELL_CONFLAGRATION_DEV, true);
            }
            m_uiConfTimer = 1000;
            m_uiConfCount = 0;
            m_uiConflagrationTimer = 20000 + rand()%1000;
        }else m_uiConflagrationTimer -= diff;
		
		// 50% nie zostawia sumona pod soba
        if(m_uiBlazeTimer < diff)
        {
			if(Unit *victim = m_creature->getVictim())
				DoCast(victim, SPELL_BLAZE);
            m_uiBlazeTimer = urand(5000,10000);
        }else m_uiBlazeTimer -= diff;
		
		// 100%
        if(m_uiFlameSearTimer < diff)
        {
            uint8 i = urand(3,5);
            for (uint8 k=0; k<i; ++k)
			    if (Unit* victim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
				    m_creature->CastSpell(victim, SPELL_FLAME_SEAR, true);	
            m_uiFlameSearTimer = 30000;
        }else m_uiFlameSearTimer -= diff;
		
        DoMeleeAttackIfReady();
    }
    void UpdateAI(const uint32 uiDiff)
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        switch (stage) 
        {
            case 0:
            {
                bsw->timedCast(SPELL_FEROCIOUS_BUTT, uiDiff);
                bsw->timedCast(SPELL_ARCTIC_BREATH, uiDiff);
                bsw->timedCast(SPELL_WHIRL, uiDiff);
                if (bsw->timedQuery(SPELL_MASSIVE_CRASH, uiDiff)) stage = 1;
                bsw->timedCast(SPELL_FROTHING_RAGE, uiDiff);
                DoMeleeAttackIfReady();
                break;
            }
            case 1:
            {
                 if (bsw->doCast(SPELL_MASSIVE_CRASH) == CAST_OK)
                     stage = 2;
                 break;
            }
            case 2:
            {
                if (pTarget = bsw->SelectUnit())
                {
                    TrampleCasted = false;
                    m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    stage = 3;
                    bsw->resetTimer(SPELL_TRAMPLE);
                    DoScriptText(-1713506,m_creature,pTarget);
                    SetCombatMovement(false);
                    m_creature->GetMotionMaster()->MoveIdle();
                }
                break;
            }
            case 3:
            {
                if (bsw->timedQuery(SPELL_TRAMPLE,uiDiff))
                {
                    pTarget->GetPosition(fPosX, fPosY, fPosZ);
                    TrampleCasted = false;
                    MovementStarted = true;
                    m_creature->GetMotionMaster()->MovePoint(1, fPosX, fPosY, fPosZ);
                    DoScriptText(-1713508,m_creature);
                    bsw->doCast(SPELL_ADRENALINE);
                    stage = 4;
                }
                break;
            }
            case 4:
            {
                if (MovementStarted)
                {
                    Map* pMap = m_creature->GetMap();
                    Map::PlayerList const &lPlayers = pMap->GetPlayers();
                    for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr)
                    {
                        Unit* pPlayer = itr->getSource();
                        if (!pPlayer) continue;
                        if (pPlayer->isAlive() && pPlayer->IsWithinDistInMap(m_creature, 5.0f))
                        {
                            bsw->doCast(SPELL_TRAMPLE, pPlayer);
                            TrampleCasted = true;
                            MovementStarted = false;
                            m_creature->GetMotionMaster()->MovementExpired();
                            m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
                        }
                    }

                } else stage = 5;
                if (TrampleCasted) stage = 5;
                break;
            }
            case 5:
            {
                if (!TrampleCasted)
                {
                    bsw->doCast(SPELL_STAGGERED_DAZE);
                    DoScriptText(-1713507,m_creature);
                }
                MovementStarted = false;
                m_creature->GetMotionMaster()->MovementExpired();
                m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
                SetCombatMovement(true);
                m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                stage = 0;
                break;
            }
        }
    }
    void UpdateAI(const uint32 uiDiff)
    {
        //Return since we have no target
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        //m_uiEarthquake_Timer
        if (m_uiEarthquake_Timer < uiDiff)
        {
            if (!m_bEarthquake)
            {
                DoCastSpellIfCan(m_creature->getVictim(), SPELL_EARTHQUAKE);
                m_bEarthquake = true;
                m_uiEarthquake_Timer = 5000;
            }
            else
            {
                DoScriptText(urand(0,1) ? SAY_SUMMON1 : SAY_SUMMON2, m_creature);

                //north
                m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_A6,true);
                m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_A7,true);
                m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_A8,true);
                m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_A9,true);
                m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_A10,true);

                //south
                m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_B6,true);
                m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_B7,true);
                m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_B8,true);
                m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_B9,true);
                m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_B10,true);

                DoScriptText(EMOTE_EARTHQUAKE, m_creature);

                m_bEarthquake = false;
                m_uiEarthquake_Timer = urand(40000, 45000);
            }
        }else m_uiEarthquake_Timer -= uiDiff;

        //m_uiTidalWave_Timer
        if (m_uiTidalWave_Timer < uiDiff)
        {
            DoCastSpellIfCan(m_creature->getVictim(), SPELL_TIDAL_WAVE);
            m_uiTidalWave_Timer = 20000;
        }else m_uiTidalWave_Timer -= uiDiff;

        if (!m_bPhase2)
        {
            //m_uiWateryGrave_Timer
            if (m_uiWateryGrave_Timer < uiDiff)
            {
                //Teleport 4 players under the waterfalls
                for(uint8 i = 0; i < 4; ++i)
                {
                    Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1);

                    if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && !pTarget->HasAuraType(SPELL_AURA_MOD_STUN) && pTarget->IsWithinDistInMap(m_creature, 45.0f))
                    {
                        switch(i)
                        {
                            case 0: pTarget->CastSpell(pTarget,SPELL_WATERY_GRAVE_1,false); break;
                            case 1: pTarget->CastSpell(pTarget,SPELL_WATERY_GRAVE_2,false); break;
                            case 2: pTarget->CastSpell(pTarget,SPELL_WATERY_GRAVE_3,false); break;
                            case 3: pTarget->CastSpell(pTarget,SPELL_WATERY_GRAVE_4,false); break;
                        }
                    }
                }

                DoScriptText(urand(0,1) ? SAY_SUMMON_BUBL1 : SAY_SUMMON_BUBL2, m_creature);
                DoScriptText(EMOTE_WATERY_GRAVE, m_creature);

                m_uiWateryGrave_Timer = 30000;
            }else m_uiWateryGrave_Timer -= uiDiff;

            //Start Phase2
            if (m_creature->GetHealthPercent() < 25.0f)
                m_bPhase2 = true;
        }
        else
        {
            //m_uiWateryGlobules_Timer
            if (m_uiWateryGlobules_Timer < uiDiff)
            {
                DoScriptText(EMOTE_WATERY_GLOBULES, m_creature);

                m_creature->CastSpell(m_creature,SPELL_SUMMON_GLOBULE_1,true);
                m_creature->CastSpell(m_creature,SPELL_SUMMON_GLOBULE_2,true);
                m_creature->CastSpell(m_creature,SPELL_SUMMON_GLOBULE_3,true);
                m_creature->CastSpell(m_creature,SPELL_SUMMON_GLOBULE_4,false);

                m_uiWateryGlobules_Timer = 25000;
            }else m_uiWateryGlobules_Timer -= uiDiff;
        }

        DoMeleeAttackIfReady();
    }
Example #16
0
void PetAI::UpdateAI(const uint32 diff)
{
    if (!m_unit->isAlive())
        return;
    Creature* creature = (m_unit->GetTypeId() == TYPEID_UNIT) ? static_cast<Creature*>(m_unit) : nullptr;
    Pet* pet = (creature && creature->IsPet()) ? static_cast<Pet*>(m_unit) : nullptr;
    
    Unit* owner = m_unit->GetMaster();
    if (!owner)
        return;

    Unit* victim = (pet && pet->GetModeFlags() & PET_MODE_DISABLE_ACTIONS) ? nullptr : m_unit->getVictim();

    if (m_updateAlliesTimer <= diff)
        // UpdateAllies self set update timer
        UpdateAllies();
    else
        m_updateAlliesTimer -= diff;

    if (inCombat && !victim)
    {
        m_unit->AttackStop(true, true);
        inCombat = false;
    }

    CharmInfo* charminfo = m_unit->GetCharmInfo();
    MANGOS_ASSERT(charminfo);

    if (charminfo->GetIsRetreating())
    {
        if (!owner->IsWithinDistInMap(m_unit, (PET_FOLLOW_DIST * 2)))
        {
            if (!m_unit->hasUnitState(UNIT_STAT_FOLLOW))
                m_unit->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);

            return;
        }
        else
            charminfo->SetIsRetreating();
    }
    else if (charminfo->GetSpellOpener() != 0) // have opener stored
    {
        uint32 minRange = charminfo->GetSpellOpenerMinRange();

        if (!(victim = m_unit->getVictim())
            || (minRange != 0 && m_unit->IsWithinDistInMap(victim, minRange)))
            charminfo->SetSpellOpener();
        else if (m_unit->IsWithinDistInMap(victim, charminfo->GetSpellOpenerMaxRange())
                && m_unit->IsWithinLOSInMap(victim))
        {
            // stop moving
            m_unit->clearUnitState(UNIT_STAT_MOVING);

            // auto turn to target
            m_unit->SetInFront(victim);

            if (victim->GetTypeId() == TYPEID_PLAYER)
                m_unit->SendCreateUpdateToPlayer((Player*)victim);

            if (owner->GetTypeId() == TYPEID_PLAYER)
                m_unit->SendCreateUpdateToPlayer((Player*)owner);

            uint32 spell_id = charminfo->GetSpellOpener();
            SpellEntry const* spellInfo = sSpellTemplate.LookupEntry<SpellEntry>(spell_id);

            Spell* spell = new Spell(m_unit, spellInfo, false);

            SpellCastResult result = spell->CheckPetCast(victim);

            if (result == SPELL_CAST_OK)
                spell->SpellStart(&(spell->m_targets));
            else
                delete spell;

            charminfo->SetSpellOpener();
        }
        else
            return;
    }
    // Auto cast (casted only in combat or persistent spells in any state)
    else if (!m_unit->IsNonMeleeSpellCasted(false))
    {
        typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
        TargetSpellList targetSpellStore;
        if (pet)
        {
            for (uint8 i = 0; i < pet->GetPetAutoSpellSize(); ++i)
            {
                uint32 spellID = pet->GetPetAutoSpellOnPos(i);
                if (!spellID)
                    continue;

                SpellEntry const* spellInfo = sSpellTemplate.LookupEntry<SpellEntry>(spellID);
                if (!spellInfo)
                    continue;

                if (!m_unit->IsSpellReady(*spellInfo))
                    continue;

                // ignore some combinations of combat state and combat/non combat spells
                if (!inCombat)
                {
                    // ignore attacking spells, and allow only self/around spells
                    if (!IsPositiveSpell(spellInfo->Id))
                        continue;

                    // non combat spells allowed
                    // only pet spells have IsNonCombatSpell and not fit this requirements:
                    // Consume Shadows, Lesser Invisibility, so ignore checks for its
                    if (!IsNonCombatSpell(spellInfo))
                    {
                        int32 duration = GetSpellDuration(spellInfo);
                        int32 cooldown = GetSpellRecoveryTime(spellInfo);

                        // allow only spell not on cooldown
                        if (cooldown != 0 && duration < cooldown)
                            continue;

                        // not allow instant kill auto casts as full health cost
                        if (IsSpellHaveEffect(spellInfo, SPELL_EFFECT_INSTAKILL))
                            continue;
                    }
                }
                // just ignore non-combat spells
                else if (IsNonCombatSpell(spellInfo))
                    continue;

                Spell* spell = new Spell(m_unit, spellInfo, false);

                if (inCombat && !m_unit->hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(victim))
                {
                    targetSpellStore.push_back(TargetSpellList::value_type(victim, spell));
                    continue;
                }
                else
                {
                    bool spellUsed = false;
                    for (GuidSet::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
                    {
                        Unit* Target = m_unit->GetMap()->GetUnit(*tar);

                        // only buff targets that are in combat, unless the spell can only be cast while out of combat
                        if (!Target)
                            continue;

                        if (spell->CanAutoCast(Target))
                        {
                            targetSpellStore.push_back(TargetSpellList::value_type(Target, spell));
                            spellUsed = true;
                            break;
                        }
                    }
                    if (!spellUsed)
                        delete spell;
                }
            }
        }

        // found units to cast on to
        if (!targetSpellStore.empty())
        {
            uint32 index = urand(0, targetSpellStore.size() - 1);

            Spell* spell  = targetSpellStore[index].second;
            Unit*  target = targetSpellStore[index].first;

            targetSpellStore.erase(targetSpellStore.begin() + index);

            SpellCastTargets targets;
            targets.setUnitTarget(target);

            if (!m_unit->HasInArc(M_PI_F, target))
            {
                m_unit->SetInFront(target);
                if (target->GetTypeId() == TYPEID_PLAYER)
                    m_unit->SendCreateUpdateToPlayer((Player*)target);

                if (owner && owner->GetTypeId() == TYPEID_PLAYER)
                    m_unit->SendCreateUpdateToPlayer((Player*)owner);
            }

            spell->SpellStart(&targets);
        }

        // deleted cached Spell objects
        for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
            delete itr->second;
    }

    // Stop here if casting spell (No melee and no movement)
    if (m_unit->IsNonMeleeSpellCasted(false))
        return;

    // we may get our actions disabled during spell casting, so do entire recheck for victim
    victim = (pet && pet->GetModeFlags() & PET_MODE_DISABLE_ACTIONS) ? nullptr : m_unit->getVictim();

    if (victim)
    {
        // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.
        // This is needed for charmed creatures, as once their target was reset other effects can trigger threat
        if (!victim->isTargetableForAttack())
        {
            DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "PetAI (guid = %u) is stopping attack.", m_unit->GetGUIDLow());
            m_unit->CombatStop();
            inCombat = false;
            
            return;
        }

        // if pet misses its target, it will also be the first in threat list
        if ((!creature || !(creature->GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_NO_MELEE))
            && m_unit->CanReachWithMeleeAttack(victim))
        {
            if (!m_unit->HasInArc(2 * M_PI_F / 3, victim))
            {
                m_unit->SetInFront(victim);
                if (victim->GetTypeId() == TYPEID_PLAYER)
                    m_unit->SendCreateUpdateToPlayer((Player*)victim);

                if (owner && owner->GetTypeId() == TYPEID_PLAYER)
                    m_unit->SendCreateUpdateToPlayer((Player*)owner);
            }

            DoMeleeAttackIfReady();
        }
        else if (!m_unit->hasUnitState(UNIT_STAT_MOVING))
            AttackStart(victim);
    }
    else if (owner)
    {
        CharmInfo* charmInfo = m_unit->GetCharmInfo();

        if (owner->isInCombat() && !(charmInfo && charmInfo->HasReactState(REACT_PASSIVE)))
            AttackStart(owner->getAttackerForHelper());
        else
        {
            if (charmInfo && charmInfo->HasCommandState(COMMAND_STAY))
            {
                //if stay command is set but we don't have stay pos set then we need to establish current pos as stay position
                if (!charminfo->IsStayPosSet())
                    charminfo->SetStayPosition(true);

                float stayPosX = charminfo->GetStayPosX();
                float stayPosY = charminfo->GetStayPosY();
                float stayPosZ = charminfo->GetStayPosZ();

                if (m_unit->GetPositionX() == stayPosX
                    && m_unit->GetPositionY() == stayPosY
                    && m_unit->GetPositionZ() == stayPosZ)
                {
                    float StayPosO = charminfo->GetStayPosO();

                    if (m_unit->hasUnitState(UNIT_STAT_MOVING))
                    {
                        m_unit->GetMotionMaster()->Clear(false);
                        m_unit->GetMotionMaster()->MoveIdle();
                    }
                    else if (m_unit->GetOrientation() != StayPosO)
                        m_unit->SetOrientation(StayPosO);
                }
                else
                    m_unit->GetMotionMaster()->MovePoint(0, stayPosX, stayPosY, stayPosZ, false);
            }
            else if (m_unit->hasUnitState(UNIT_STAT_FOLLOW))
            {
                if (owner->IsWithinDistInMap(m_unit, PET_FOLLOW_DIST))
                {
                    m_unit->GetMotionMaster()->Clear(false);
                    m_unit->GetMotionMaster()->MoveIdle();
                }
            }
            else if (charmInfo && charmInfo->HasCommandState(COMMAND_FOLLOW)
                && !owner->IsWithinDistInMap(m_unit, (PET_FOLLOW_DIST * 2)))
                m_unit->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
        }
    }
}
Example #17
0
    void UpdateAI(const uint32 uiDiff)
    {
        if (m_bIsActiveCheck)
        {
            if (!m_bIsActived && Active_Timer < uiDiff)
            {
                m_bIsActived = true;
                Active_Timer = 1000;
            }else Active_Timer -= uiDiff;
        }
        else
        {
            if (Active_Timer < uiDiff)
            {
                if(m_pInstance)
                {
                    bool m_bIsAlive = false;
                    Creature* pStalagg;
                    Creature* pFeugen;
                    if (pStalagg = ((Creature*)Unit::GetUnit((*m_creature), m_pInstance->GetData64(DATA_STALAGG))))
                        if (pStalagg->isAlive())
                            m_bIsAlive = true;
                    if (pFeugen = ((Creature*)Unit::GetUnit((*m_creature), m_pInstance->GetData64(DATA_FEUGEN))))
                        if (pFeugen->isAlive())
                            m_bIsAlive = true;

                    if (!m_bIsAlive)
                    {
                        m_bIsActiveCheck = true;
                        Active_Timer = 15000;
                    }
                    else
                    {
                        if (pStalagg->isInCombat() && pFeugen->isInCombat())
                        {
                            if (SwitchTarget_Timer < uiDiff)
                            {
                                Unit* pStalaggTarget;
                                Unit* pFeugenTarget;
                                float StalaggTargetThreat;
                                float FeugenTargetThreat;

                                // Get Stalagg's target threat
                                if (pStalagg && pStalagg->isAlive())
                                {
                                    if (pStalaggTarget = pStalagg->getVictim())
                                        StalaggTargetThreat = m_creature->getThreatManager().getThreat(pStalaggTarget);
                                }
                                // Get Feugen's target threat
                                if (pFeugen && pFeugen->isAlive())
                                {
                                    if (pFeugenTarget = pFeugen->getVictim())
                                        FeugenTargetThreat = m_creature->getThreatManager().getThreat(pFeugenTarget);
                                }

                                // Switch Feugen's target from Stalagg
                                if (pStalagg && pStalagg->isAlive())
                                {
                                    if (pFeugen && pFeugen->isAlive())
                                    {
                                        HostilReference* ref = pFeugen->getThreatManager().getOnlineContainer().getReferenceByTarget(pFeugenTarget);
                                        if (ref)
                                        {
                                            pStalagg->CastSpell(pFeugenTarget, 54517, true);
                                            ((Player*)pFeugenTarget)->TeleportTo(pFeugenTarget->GetMapId(), pStalagg->GetPositionX(), pStalagg->GetPositionY(), pStalagg->GetPositionZ(), 0, TELE_TO_NOT_LEAVE_COMBAT);
                                            ref->removeReference();
                                            pStalagg->AddThreat(pFeugenTarget, FeugenTargetThreat);
                                            pStalagg->AI()->AttackStart(pFeugenTarget);
                                        }
                                    }
                                }
                                // Switch Stalagg's target from Feugen
                                if (pFeugen && pFeugen->isAlive())
                                {
                                    if (pStalagg && pStalagg->isAlive())
                                    {
                                        HostilReference* ref = pStalagg->getThreatManager().getOnlineContainer().getReferenceByTarget(pStalaggTarget);
                                        if (ref)
                                        {
                                            pFeugen->CastSpell(pStalaggTarget, 54517, true);
                                            ((Player*)pStalaggTarget)->TeleportTo(pStalaggTarget->GetMapId(), pFeugen->GetPositionX(), pFeugen->GetPositionY(), pFeugen->GetPositionZ(), 0, TELE_TO_NOT_LEAVE_COMBAT);
                                            ref->removeReference();
                                            pFeugen->AddThreat(pStalaggTarget, StalaggTargetThreat);
                                            pFeugen->AI()->AttackStart(pStalaggTarget);
                                        }
                                    }
                                }

                                SwitchTarget_Timer = 20000;
                            }else SwitchTarget_Timer -= uiDiff;
                        }
                        else if (pStalagg->isInCombat() || pFeugen->isInCombat())
                        {
                            if (m_pInstance)
                                m_pInstance->SetData(TYPE_THADDIUS, IN_PROGRESS);
                        }
                        else if (!pStalagg->isInCombat() && !pFeugen->isInCombat())
                        {
                            if (m_pInstance)
                                m_pInstance->SetData(TYPE_THADDIUS, NOT_STARTED);
                        }

                        Active_Timer = 1000;
                    }
                }
            }else Active_Timer -= uiDiff;
        }

        if (!m_creature->SelectHostilTarget() || !m_creature->getVictim())
            return;

        if (ChainLightning_Timer < uiDiff)
        {
            DoCast(m_creature, m_bIsHeroicMode ? H_SPELL_CHAIN_LIGHTNING : SPELL_CHAIN_LIGHTNING);
            ChainLightning_Timer = 15000;
        }else ChainLightning_Timer -= uiDiff;

        if(m_bIsPolarityShift)
        {
            // workaround for POLARITY_SHIFT
            if (PolarityShift_Timer < uiDiff)
            {
                Map *map = m_creature->GetMap();
                if (map->IsDungeon())
                {
                    Map::PlayerList const &PlayerList = map->GetPlayers();

                    if (PlayerList.isEmpty())
                        return;

                    for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
                        if (i->getSource()->isAlive() && i->getSource()->isTargetableForAttack())
                        {
                            switch(rand()%2)
                            {
                                case 0:
                                    if (i->getSource()->HasAura(SPELL_CHARGE_NEGATIVE_NEARDMG))
                                        i->getSource()->RemoveAurasDueToSpell(SPELL_CHARGE_NEGATIVE_NEARDMG);
                                    i->getSource()->CastSpell(i->getSource(), SPELL_CHARGE_POSITIVE_NEARDMG, true);
                                    break;
                                case 1:
                                    if (i->getSource()->HasAura(SPELL_CHARGE_POSITIVE_NEARDMG))
                                        i->getSource()->RemoveAurasDueToSpell(SPELL_CHARGE_POSITIVE_NEARDMG);
                                    i->getSource()->CastSpell(i->getSource(), SPELL_CHARGE_NEGATIVE_NEARDMG, true);
                                    break;
                            }
                        }
                }
                m_bIsPolarityShift = false;
                PolarityShift_Timer = 27000;
            }else PolarityShift_Timer -= uiDiff;
        }
        else
        {
            if(PolarityShift_Timer < uiDiff)
            {
      	        DoCast(m_creature, SPELL_POLARITY_SHIFT); // need core support
                m_bIsPolarityShift = true;
                PolarityShift_Timer = 3000;
            }else PolarityShift_Timer -= uiDiff;
        }

        if (Enrage_Timer < uiDiff)
        {
            DoCast(m_creature, SPELL_BESERK);
            Enrage_Timer = 300000;
        }else Enrage_Timer -= uiDiff;

        if (Scream_Timer < uiDiff)
        {
            switch(rand()%4)
            {
                case 0: DoScriptText(SAY_SCREAM1, m_creature);break;
                case 1: DoScriptText(SAY_SCREAM2, m_creature);break;
                case 2: DoScriptText(SAY_SCREAM3, m_creature);break;
                case 3: DoScriptText(SAY_SCREAM4, m_creature);break;
            }
            Scream_Timer = 60000+rand()%30000;
        }else Scream_Timer -= uiDiff;

        if (RangeCheck_Timer < uiDiff)
        {
            m_bInMeleeRange = false;
            std::list<HostilReference *> t_list = m_creature->getThreatManager().getThreatList();
            for(std::list<HostilReference *>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
            {
                Unit* pTarget = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());

                //if in melee range
                if (pTarget && pTarget->IsWithinDistInMap(m_creature, ATTACK_DISTANCE))
                {
                    m_bInMeleeRange = true;
                    break;
                }
            }

            if (!m_bInMeleeRange)
                DoCast(SelectUnit(SELECT_TARGET_TOPAGGRO,0), SPELL_BALL_LIGHTNING);

            RangeCheck_Timer = 2000;
        }else RangeCheck_Timer -= uiDiff;

        //if nobody is in melee range
        if (m_bInMeleeRange)
            DoMeleeAttackIfReady();
    }
Example #18
0
        void UpdateAI(uint32 diff) override
        {
            if (!CanAttack && Intro)
            {
                if (AggroTimer <= diff)
                {
                    CanAttack = true;
                    me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    AggroTimer=19000;
                }
                else
                {
                    AggroTimer-=diff;
                    return;
                }
            }
            // to prevent abuses during phase 2
            if (Phase == 2 && !me->GetVictim() && me->IsInCombat())
            {
                EnterEvadeMode();
                return;
            }
            // Return since we have no target
            if (!UpdateVictim())
                return;

            if (Phase == 1 || Phase == 3)
            {
                // ShockBlastTimer
                if (ShockBlastTimer <= diff)
                {
                    // Shock Burst
                    // Randomly used in Phases 1 and 3 on Vashj's target, it's a Shock spell doing 8325-9675 nature damage and stunning the target for 5 seconds, during which she will not attack her target but switch to the next person on the aggro list.
                    DoCastVictim(SPELL_SHOCK_BLAST);
                    me->TauntApply(me->GetVictim());

                    ShockBlastTimer = 1000 + rand32() % 14000;       // random cooldown
                } else ShockBlastTimer -= diff;

                // StaticChargeTimer
                if (StaticChargeTimer <= diff)
                {
                    // Static Charge
                    // Used on random people (only 1 person at any given time) in Phases 1 and 3, it's a debuff doing 2775 to 3225 Nature damage to the target and everybody in about 5 yards around it, every 1 seconds for 30 seconds. It can be removed by Cloak of Shadows, Iceblock, Divine Shield, etc, but not by Cleanse or Dispel Magic.
                    Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true);
                    if (target && !target->HasAura(SPELL_STATIC_CHARGE_TRIGGER))
                        DoCast(target, SPELL_STATIC_CHARGE_TRIGGER); // cast Static Charge every 2 seconds for 20 seconds

                    StaticChargeTimer = 10000 + rand32() % 20000;
                } else StaticChargeTimer -= diff;

                // EntangleTimer
                if (EntangleTimer <= diff)
                {
                    if (!Entangle)
                    {
                        // Entangle
                        // Used in Phases 1 and 3, it casts Entangling Roots on everybody in a 15 yard radius of Vashj, immobilzing them for 10 seconds and dealing 500 damage every 2 seconds. It's not a magic effect so it cannot be dispelled, but is removed by various buffs such as Cloak of Shadows or Blessing of Freedom.
                        DoCastVictim(SPELL_ENTANGLE);
                        Entangle = true;
                        EntangleTimer = 10000;
                    }
                    else
                    {
                        CastShootOrMultishot();
                        Entangle = false;
                        EntangleTimer = 20000 + rand32() % 5000;
                    }
                } else EntangleTimer -= diff;

                // Phase 1
                if (Phase == 1)
                {
                    // Start phase 2
                    if (HealthBelowPct(70))
                    {
                        // 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;

                        me->GetMotionMaster()->Clear();
                        DoTeleportTo(MIDDLE_X, MIDDLE_Y, MIDDLE_Z);

                        for (uint8 i = 0; i < 4; ++i)
                            if (Creature* creature = me->SummonCreature(SHIED_GENERATOR_CHANNEL, ShieldGeneratorChannelPos[i][0],  ShieldGeneratorChannelPos[i][1],  ShieldGeneratorChannelPos[i][2],  ShieldGeneratorChannelPos[i][3], TEMPSUMMON_CORPSE_DESPAWN, 0))
                                ShieldGeneratorChannel[i] = creature->GetGUID();

                        Talk(SAY_PHASE2);
                    }
                }
                // Phase 3
                else
                {
                    // SummonSporebatTimer
                    if (SummonSporebatTimer <= diff)
                    {
                        if (Creature* sporebat = me->SummonCreature(TOXIC_SPOREBAT, SPOREBAT_X, SPOREBAT_Y, SPOREBAT_Z, SPOREBAT_O, TEMPSUMMON_CORPSE_DESPAWN, 0))
                            if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
                                sporebat->AI()->AttackStart(target);

                        // summon sporebats faster and faster
                        if (SummonSporebatStaticTimer > 1000)
                            SummonSporebatStaticTimer -= 1000;

                        SummonSporebatTimer = SummonSporebatStaticTimer;

                        if (SummonSporebatTimer < 5000)
                            SummonSporebatTimer = 5000;

                    } else SummonSporebatTimer -= diff;
                }

                // Melee attack
                DoMeleeAttackIfReady();

                // CheckTimer - used to check if somebody is in melee range
                if (CheckTimer <= diff)
                {
                    bool inMeleeRange = false;
                    std::list<HostileReference*> t_list = me->getThreatManager().getThreatList();
                    for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
                    {
                        Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
                        if (target && target->IsWithinDistInMap(me, 5)) // if in melee range
                        {
                            inMeleeRange = true;
                            break;
                        }
                    }

                    // if nobody is in melee range
                    if (!inMeleeRange)
                        CastShootOrMultishot();

                    CheckTimer = 5000;
                } else CheckTimer -= diff;
            }
            // Phase 2
            else
            {
                // ForkedLightningTimer
                if (ForkedLightningTimer <= diff)
                {
                    // Forked Lightning
                    // Used constantly in Phase 2, it shoots out completely randomly targeted bolts of lightning which hit everybody in a roughtly 60 degree cone in front of Vashj for 2313-2687 nature damage.
                    Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0);

                    if (!target)
                        target = me->GetVictim();

                    DoCast(target, SPELL_FORKED_LIGHTNING);

                    ForkedLightningTimer = 2000 + rand32() % 6000;
                } else ForkedLightningTimer -= diff;

                // EnchantedElementalTimer
                if (EnchantedElementalTimer <= diff)
                {
                    me->SummonCreature(ENCHANTED_ELEMENTAL, ElementPos[EnchantedElementalPos][0], ElementPos[EnchantedElementalPos][1], ElementPos[EnchantedElementalPos][2], ElementPos[EnchantedElementalPos][3], TEMPSUMMON_CORPSE_DESPAWN, 0);

                    if (EnchantedElementalPos == 7)
                        EnchantedElementalPos = 0;
                    else
                        ++EnchantedElementalPos;

                    EnchantedElementalTimer = 10000 + rand32() % 5000;
                } else EnchantedElementalTimer -= diff;

                // TaintedElementalTimer
                if (TaintedElementalTimer <= diff)
                {
                    uint32 pos = rand32() % 8;
                    me->SummonCreature(TAINTED_ELEMENTAL, ElementPos[pos][0], ElementPos[pos][1], ElementPos[pos][2], ElementPos[pos][3], TEMPSUMMON_DEAD_DESPAWN, 0);

                    TaintedElementalTimer = 120000;
                } else TaintedElementalTimer -= diff;

                // CoilfangEliteTimer
                if (CoilfangEliteTimer <= diff)
                {
                    uint32 pos = rand32() % 3;
                    Creature* coilfangElite = me->SummonCreature(COILFANG_ELITE, CoilfangElitePos[pos][0], CoilfangElitePos[pos][1], CoilfangElitePos[pos][2], CoilfangElitePos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
                    if (coilfangElite)
                    {
                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
                            coilfangElite->AI()->AttackStart(target);
                        else if (me->GetVictim())
                            coilfangElite->AI()->AttackStart(me->GetVictim());
                    }
                    CoilfangEliteTimer = 45000 + rand32() % 5000;
                } else CoilfangEliteTimer -= diff;

                // CoilfangStriderTimer
                if (CoilfangStriderTimer <= diff)
                {
                    uint32 pos = rand32() % 3;
                    if (Creature* CoilfangStrider = me->SummonCreature(COILFANG_STRIDER, CoilfangStriderPos[pos][0], CoilfangStriderPos[pos][1], CoilfangStriderPos[pos][2], CoilfangStriderPos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000))
                    {
                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
                            CoilfangStrider->AI()->AttackStart(target);
                        else if (me->GetVictim())
                            CoilfangStrider->AI()->AttackStart(me->GetVictim());
                    }
                    CoilfangStriderTimer = 60000 + rand32() % 10000;
                } else CoilfangStriderTimer -= diff;

                // CheckTimer
                if (CheckTimer <= diff)
                {
                    // Start Phase 3
                    if (instance->GetData(DATA_CANSTARTPHASE3))
                    {
                        // set life 50%
                        me->SetHealth(me->CountPctFromMaxHealth(50));

                        me->RemoveAurasDueToSpell(SPELL_MAGIC_BARRIER);

                        Talk(SAY_PHASE3);

                        Phase = 3;

                        // return to the tank
                        me->GetMotionMaster()->MoveChase(me->GetVictim());
                    }
                    CheckTimer = 1000;
                } else CheckTimer -= diff;
            }
        }
Example #19
0
void WorldSession::HandlePetAction(WorldPacket& recv_data)
{
    ObjectGuid petGuid;
    uint32 data;
    ObjectGuid targetGuid;
    float x, y, z;
    recv_data >> petGuid;
    recv_data >> data;
    recv_data >> targetGuid;
    recv_data >> x >> y >> z;

    uint32 spellid = UNIT_ACTION_BUTTON_ACTION(data);
    uint8 flag = UNIT_ACTION_BUTTON_TYPE(data);             // delete = 0x07 CastSpell = C1

    DETAIL_LOG("HandlePetAction: %s flag is %u, spellid is %u, target %s.", petGuid.GetString().c_str(), uint32(flag), spellid, targetGuid.GetString().c_str());

    // used also for charmed creature/player
    Unit* pet = _player->GetMap()->GetUnit(petGuid);
    if (!pet)
    {
        sLog.outError("HandlePetAction: %s not exist.", petGuid.GetString().c_str());
        return;
    }

    if (_player->GetObjectGuid() != pet->GetCharmerOrOwnerGuid())
    {
        sLog.outError("HandlePetAction: %s isn't controlled by %s.", petGuid.GetString().c_str(), _player->GetGuidStr().c_str());
        return;
    }

    if (!pet->isAlive())
        return;

    if (pet->GetTypeId() == TYPEID_PLAYER && pet->GetCharmer()->GetTypeId() == TYPEID_PLAYER)
    {
        // controller player cannot use controlled player's spells
        if (flag != (ACT_COMMAND || ACT_REACTION))
            return;
    }
    else if (((Creature*)pet)->IsPet())
    {
        // pet can have action bar disabled
        if (((Pet*)pet)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)
            return;
    }

    CharmInfo* charmInfo = pet->GetCharmInfo();
    if (!charmInfo)
    {
        sLog.outError("WorldSession::HandlePetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId());
        return;
    }

    switch (flag)
    {
        case ACT_COMMAND:                                   // 0x07
            switch (spellid)
            {
                case COMMAND_STAY:                          // flat=1792  // STAY
                {
                    pet->StopMoving();
                    pet->AttackStop(true, true);
                    pet->GetMotionMaster()->Clear();
                    ((Pet*)pet)->SetStayPosition(true);
                    ((Pet*)pet)->SetIsRetreating();
                    ((Pet*)pet)->SetSpellOpener();
                    charmInfo->SetCommandState(COMMAND_STAY);
                    break;
                }
                case COMMAND_FOLLOW:                        // spellid=1792  // FOLLOW
                {
                    pet->StopMoving();
                    pet->AttackStop(true, true);
                    pet->GetMotionMaster()->Clear();
                    ((Pet*)pet)->SetStayPosition();
                    ((Pet*)pet)->SetIsRetreating(true);
                    ((Pet*)pet)->SetSpellOpener();
                    charmInfo->SetCommandState(COMMAND_FOLLOW);
                    break;
                }
                case COMMAND_ATTACK:                        // spellid=1792  // ATTACK
                {
                    ((Pet*)pet)->SetIsRetreating();
                    ((Pet*)pet)->SetSpellOpener();

                    Unit* targetUnit = targetGuid ? _player->GetMap()->GetUnit(targetGuid) : nullptr;

                    if (targetUnit && targetUnit != pet && targetUnit->isTargetableForAttack() && targetUnit->isInAccessablePlaceFor((Creature*)pet))
                    {
                        _player->SetInCombatState(true, targetUnit);

                        // This is true if pet has no target or has target but targets differs.
                        if (pet->getVictim() != targetUnit)
                        {
                            pet->AttackStop();
                            pet->GetMotionMaster()->Clear();

                            if (((Creature*)pet)->AI())
                            {
                                ((Creature*)pet)->AI()->AttackStart(targetUnit);
                                 // 10% chance to play special warlock pet attack talk, else growl
                                if (((Creature*)pet)->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && roll_chance_i(10))
                                    pet->SendPetTalk((uint32)PET_TALK_ATTACK);

                                pet->SendPetAIReaction();
                            }
                            else
                                pet->Attack(targetUnit, true);
                        }
                    }

                    break;
                }
                case COMMAND_ABANDON:                       // abandon (hunter pet) or dismiss (summoned pet)
                {
                    Creature* petC = (Creature*)pet;
                    if (petC->IsPet())

                    {
                        Pet* p = (Pet*)petC;
                        if (p->getPetType() == HUNTER_PET)
                            p->Unsummon(PET_SAVE_AS_DELETED, _player);
                        else
                            // dismissing a summoned pet is like killing them (this prevents returning a soulshard...)
                            p->SetDeathState(CORPSE);
                    }
                    else                                    // charmed
                        _player->Uncharm();

                    if (petC->IsTemporarySummon()) // special case when pet was temporary summon through DoSummonPossesed
                    {
                        petC->ForcedDespawn();
                        return;
                    }

                    ((Pet*)pet)->SetStayPosition();
                    break;
                }
                default:
                    sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid);
            }
            break;
        case ACT_REACTION:                                  // 0x6
            switch (spellid)
            {
                case REACT_PASSIVE:                         // passive
                {
                    pet->AttackStop(true, true);
                    ((Pet*)pet)->SetSpellOpener();
                }
                case REACT_DEFENSIVE:                       // recovery
                case REACT_AGGRESSIVE:                      // activete
                {
                    charmInfo->SetReactState(ReactStates(spellid));
                    break;
                }
            }
            break;
        case ACT_DISABLED:                                  // 0x81    spell (disabled), ignore
        case ACT_PASSIVE:                                   // 0x01
        case ACT_ENABLED:                                   // 0xC1    spell
        {
            ((Pet*)pet)->SetIsRetreating();
            ((Pet*)pet)->SetSpellOpener();

            Unit* unit_target = targetGuid ? _player->GetMap()->GetUnit(targetGuid) : nullptr;

            // do not cast unknown spells
            SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid);
            if (!spellInfo)
            {
                sLog.outError("WORLD: unknown PET spell id %i", spellid);
                return;
            }

            if (pet->GetCharmInfo() && pet->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
                return;

            for (int i = 0; i < MAX_EFFECT_INDEX; ++i)
            {
                SpellEffectEntry const* spellEffect = spellInfo->GetSpellEffect(SpellEffectIndex(i));
                if (!spellEffect)
                    continue;

                if (spellEffect->EffectImplicitTargetA == TARGET_ALL_ENEMY_IN_AREA
                    || spellEffect->EffectImplicitTargetA == TARGET_ALL_ENEMY_IN_AREA_INSTANT
                    || spellEffect->EffectImplicitTargetA == TARGET_ALL_ENEMY_IN_AREA_CHANNELED)
                    return;
            }

            // do not cast not learned spells
            if (!pet->HasSpell(spellid) || IsPassiveSpell(spellInfo))
                return;

            pet->clearUnitState(UNIT_STAT_MOVING);

            Spell* spell = new Spell(pet, spellInfo, false);

            SpellCastResult result = spell->CheckPetCast(unit_target);

            const SpellRangeEntry* sRange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex);

            if (unit_target && !(pet->IsWithinDistInMap(unit_target, sRange->maxRange) && pet->IsWithinLOSInMap(unit_target)) 
                && !(GetPlayer()->IsFriendlyTo(unit_target) || pet->HasAuraType(SPELL_AURA_MOD_POSSESS)))
            {
                ((Pet*)pet)->SetSpellOpener(spellid, sRange->minRange, sRange->maxRange);
                spell->finish(false);
                delete spell;

                pet->AttackStop();
                pet->GetMotionMaster()->Clear();

                ((Creature*)pet)->AI()->AttackStart(unit_target);
                 // 10% chance to play special warlock pet attack talk, else growl
                if (((Creature*)pet)->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != unit_target && roll_chance_i(10))
                    pet->SendPetTalk((uint32)PET_TALK_ATTACK);

                pet->SendPetAIReaction();

                return;
            }

            // auto turn to target unless possessed
            if (result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS))
            {
                if (unit_target)
                {
                    pet->SetInFront(unit_target);
                    if (unit_target->GetTypeId() == TYPEID_PLAYER)
                        pet->SendCreateUpdateToPlayer((Player*)unit_target);
                }
                else if (Unit* unit_target2 = spell->m_targets.getUnitTarget())
                {
                    pet->SetInFront(unit_target2);
                    if (unit_target2->GetTypeId() == TYPEID_PLAYER)
                        pet->SendCreateUpdateToPlayer((Player*)unit_target2);
                }
                if (Unit* powner = pet->GetCharmerOrOwner())
                    if (powner->GetTypeId() == TYPEID_PLAYER)
                        pet->SendCreateUpdateToPlayer((Player*)powner);
                result = SPELL_CAST_OK;
            }

            if (result == SPELL_CAST_OK)
            {
                ((Creature*)pet)->AddCreatureSpellCooldown(spellid);

                unit_target = spell->m_targets.getUnitTarget();

                if (unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS))
                {
                    // This is true if pet has no target or has target but targets differs.
                    if (pet->getVictim() != unit_target)
                    {
                        pet->AttackStop();
                        pet->GetMotionMaster()->Clear();

                        _player->SetInCombatState(true, unit_target);

                        if (((Creature*)pet)->AI())
                        {
                            ((Creature*)pet)->AI()->AttackStart(unit_target);
                             // 10% chance to play special warlock pet attack talk, else growl
                            if (((Creature*)pet)->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != unit_target && roll_chance_i(10))
                                pet->SendPetTalk((uint32)PET_TALK_ATTACK);

                            pet->SendPetAIReaction();
                        }

                        else
                            pet->Attack(unit_target, true);
                    }
                }

                ((Pet*)pet)->SetSpellOpener();
                spell->SpellStart(&(spell->m_targets));
            }
            else
            {
                if (pet->HasAuraType(SPELL_AURA_MOD_POSSESS))
                    Spell::SendCastResult(GetPlayer(), spellInfo, 0, result);
                else
                {
                    Unit* owner = pet->GetCharmerOrOwner();
                    if (owner && owner->GetTypeId() == TYPEID_PLAYER)
                        Spell::SendCastResult((Player*)owner, spellInfo, 0, result, true);
                }

                if (!((Creature*)pet)->HasSpellCooldown(spellid))
                    GetPlayer()->SendClearCooldown(spellid, pet);

                ((Pet*)pet)->SetSpellOpener();
                spell->finish(false);
                delete spell;
            }
            break;
        }
        default:
            sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid);
    }
}
Example #20
0
    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;
        }
        //Return since we have no target
        if (!UpdateVictim() )
            return;

        if(Phase == 1 || Phase == 3)
        {
            //ShockBlast_Timer
            if (ShockBlast_Timer < diff)
            {
                //Shock Burst
                //Randomly used in Phases 1 and 3 on Vashj's target, it's a Shock spell doing 8325-9675 nature damage and stunning the target for 5 seconds, during which she will not attack her target but switch to the next person on the aggro list.
                DoCast(m_creature->getVictim(), SPELL_SHOCK_BLAST);
                m_creature->TauntApply(m_creature->getVictim());

                ShockBlast_Timer = 1000+rand()%14000;       //random cooldown
            }else ShockBlast_Timer -= diff;

            //StaticCharge_Timer
            if(StaticCharge_Timer < diff)
            {
                //Static Charge
                //Used on random people (only 1 person at any given time) in Phases 1 and 3, it's a debuff doing 2775 to 3225 Nature damage to the target and everybody in about 5 yards around it, every 1 seconds for 30 seconds. It can be removed by Cloak of 3s, Iceblock, Divine Shield, etc, but not by Cleanse or Dispel Magic.
                Unit *target = NULL;
                target = SelectUnit(SELECT_TARGET_RANDOM, 0);

                if(target && !target->HasAura(SPELL_STATIC_CHARGE_TRIGGER, 0) && target->GetTypeId() == TYPEID_PLAYER && !target->isDead())
                                                            //cast Static Charge every 2 seconds for 20 seconds
                        DoCast(target, SPELL_STATIC_CHARGE_TRIGGER);

                StaticCharge_Timer = 10000+rand()%20000;    //blizzlike
            }else StaticCharge_Timer -= diff;

            //Entangle_Timer
            if (Entangle_Timer < diff)
            {
                if(!Entangle)
                {
                    //Entangle
                    //Used in Phases 1 and 3, it casts Entangling Roots on everybody in a 15 yard radius of Vashj, immobilzing them for 10 seconds and dealing 500 damage every 2 seconds. It's not a magic effect so it cannot be dispelled, but is removed by various buffs such as Cloak of Shadows or Blessing of Freedom.
                    DoCast(m_creature->getVictim(), SPELL_ENTANGLE);
                    Entangle = true;
                    Entangle_Timer = 10000;
                }
                else
                {
                    CastShootOrMultishot();
                    Entangle = false;
                    Entangle_Timer = 20000+rand()%5000;
                }
            }else Entangle_Timer -= diff;

            //Phase 1
            if(Phase == 1)
            {
                //Start phase 2
                if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 70)
                {
                    //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->GetMotionMaster()->Clear();
                    DoTeleportTo(MIDDLE_X, MIDDLE_Y, MIDDLE_Z);

                    Creature *pCreature;
                    for(uint8 i = 0; i < 4; i++)
                    {
                        pCreature = m_creature->SummonCreature(SHIED_GENERATOR_CHANNEL, ShieldGeneratorChannelPos[i][0],  ShieldGeneratorChannelPos[i][1],  ShieldGeneratorChannelPos[i][2],  ShieldGeneratorChannelPos[i][3], TEMPSUMMON_CORPSE_DESPAWN, 0);
                        if (pCreature)
                            ShieldGeneratorChannel[i] = pCreature->GetGUID();
                    }
                    DoScriptText(SAY_PHASE2, m_creature);
                }
            }
            //Phase 3
            else
            {
                //SummonSporebat_Timer
                if(SummonSporebat_Timer < diff)
                {
                    Creature *Sporebat = NULL;
                    Sporebat = m_creature->SummonCreature(TOXIC_SPOREBAT, SPOREBAT_X, SPOREBAT_Y, SPOREBAT_Z, SPOREBAT_O, TEMPSUMMON_CORPSE_DESPAWN, 0);

                    if(Sporebat)
                    {
                        Unit *target = NULL;
                        target = SelectUnit(SELECT_TARGET_RANDOM, 0);
                        if(target)
                            Sporebat->AI()->AttackStart(target);
                    }

                    //summon sporebats faster and faster
                    if(SummonSporebat_StaticTimer > 1000)
                        SummonSporebat_StaticTimer -= 1000;

                    SummonSporebat_Timer = SummonSporebat_StaticTimer;

                    if(SummonSporebat_Timer < 5000)
                        SummonSporebat_Timer = 5000;

                }else SummonSporebat_Timer -= diff;
            }

            //Melee attack
            DoMeleeAttackIfReady();

            //Check_Timer - used to check if somebody is in melee range
            if(Check_Timer < diff)
            {
                bool InMeleeRange = false;
                Unit *target;
                std::list<HostilReference *> t_list = m_creature->getThreatManager().getThreatList();
                for(std::list<HostilReference *>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
                {
                    target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());
                                                            //if in melee range
                    if(target && target->IsWithinDistInMap(m_creature, 5))
                    {
                        InMeleeRange = true;
                        break;
                    }
                }

                //if nobody is in melee range
                if(!InMeleeRange)
                CastShootOrMultishot();

                Check_Timer = 5000;
            }else Check_Timer -= diff;
        }
        //Phase 2
        else
        {
            //ForkedLightning_Timer
            if(ForkedLightning_Timer < diff)
            {
                //Forked Lightning
                //Used constantly in Phase 2, it shoots out completely randomly targeted bolts of lightning which hit everybody in a roughtly 60 degree cone in front of Vashj for 2313-2687 nature damage.
                Unit *target = NULL;
                target = SelectUnit(SELECT_TARGET_RANDOM, 0);

                if(!target)
                    target = m_creature->getVictim();
                    
                DoCast(target, SPELL_FORKED_LIGHTNING);    
                
                ForkedLightning_Timer = 2000+rand()%6000;   //blizzlike
            }else ForkedLightning_Timer -= diff;

            //EnchantedElemental_Timer
            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_CORPSE_DESPAWN, 0);

                if(EnchantedElemental_Pos == 7)
                    EnchantedElemental_Pos = 0;
                else
                    EnchantedElemental_Pos++;

                EnchantedElemental_Timer = 10000+rand()%5000;
            }else EnchantedElemental_Timer -= diff;

            //TaintedElemental_Timer
            if(TaintedElemental_Timer < diff)
            {
                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_DEAD_DESPAWN, 0);

                TaintedElemental_Timer = 120000;
            }else TaintedElemental_Timer -= diff;

            //CoilfangElite_Timer
            if(CoilfangElite_Timer < diff)
            {
                uint32 pos = rand()%3;
                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;
            }else CoilfangElite_Timer -= diff;

            //CoilfangStrider_Timer
            if(CoilfangStrider_Timer < diff)
            {
                uint32 pos = rand()%3;
                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;
            }else CoilfangStrider_Timer -= diff;

            //Check_Timer
            if(Check_Timer < diff)
            {
                //Start Phase 3
                if(pInstance && pInstance->GetData(DATA_CANSTARTPHASE3))
                {
                    //set life 50%
                    m_creature->SetHealth(m_creature->GetMaxHealth()/2);

                    m_creature->RemoveAurasDueToSpell(SPELL_MAGIC_BARRIER);

                    DoScriptText(SAY_PHASE3, m_creature);

                    Phase = 3;

                    //return to the tank
                    m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
                }
                
                
                  // check item tainted core. if player has item, cast root. if not has item and is rooted, remove root          
        InstanceMap::PlayerList const &playerliste = ((InstanceMap*)m_creature->GetMap())->GetPlayers();
        InstanceMap::PlayerList::const_iterator it;
        Map::PlayerList const &PlayerList = ((InstanceMap*)m_creature->GetMap())->GetPlayers();
        for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
                    {
                    Player* i_pl = i->getSource();
                    {
                    if(i_pl->HasItemCount(31088, 1, false))
                    {
                            if(i_pl->HasAura(39666,0)) i_pl->RemoveAurasDueToSpell(39666); // cloak of shadowx
                            if(!i_pl->HasAura(38132,0))
                                i_pl->CastSpell(i_pl, 38132, false); // spell root
                    }
                        else if(i_pl->HasAura(38132,0))
                            i_pl->RemoveAurasDueToSpell(38132);
                    }
                    }
                    
                
                
                
                Check_Timer = 1000;
            }else Check_Timer -= diff;
        }
    }
    void UpdateAI(const uint32 diff)
    {
        //Sounds OOC, Kiljaeden Orders
        if(!m_creature->getVictim())
        {
            if(m_uiKJOrdersTimer < diff)
            {
		        switch (rand()%5)
		        {
			        case 0: DoPlaySoundToSet(m_creature, SAY_KJ_OFFCOMBAT1); break;
			        case 1: DoPlaySoundToSet(m_creature, SAY_KJ_OFFCOMBAT2); break;
			        case 2: DoPlaySoundToSet(m_creature, SAY_KJ_OFFCOMBAT3); break;
                    case 3: DoPlaySoundToSet(m_creature, SAY_KJ_OFFCOMBAT4); break;
                    case 4: DoPlaySoundToSet(m_creature, SAY_KJ_OFFCOMBAT5); break;
		        }
                m_uiKJOrdersTimer = 60000;
            }else m_uiKJOrdersTimer -= diff;
        }

        //Rebirth After Phase1
        if(pInstance && pInstance->GetData(DATA_DECIVER) == SPECIAL)
        {
            m_creature->setFaction(14);
            m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
            pInstance->SetData(DATA_KILJAEDEN_EVENT, IN_PROGRESS);
            pInstance->SetData(DATA_DECIVER, NOT_STARTED); 
        }

        if(!m_creature->SelectHostileTarget() || !m_creature->getVictim())
               return;

        //FireBloom Damage WorkArround
        if(m_uiFireBloomCheck < diff)
        {
            if(m_uiFireBloomCount < 10)
                for(uint8 i=0; i<5; ++i)
                {
                    if(Unit* FireTarget = m_creature->GetMap()->GetUnit(m_uiFireBloomTarget[i]))
                        if(FireTarget->isAlive())
                            FireTarget->CastSpell(FireTarget, SPELL_FIREBLOOM_EFF, true);
                }
            ++m_uiFireBloomCount;
            m_uiFireBloomCheck = 2000;
        }else m_uiFireBloomCheck -= diff;

        if((m_uiOrbTimer < diff) && !m_bBoolOrb)
        {
            switch (rand()%4)
		        {
			        case 0: DoPlaySoundToSet(m_creature, SAY_KALEC_ORB_READY1); break;
			        case 1: DoPlaySoundToSet(m_creature, SAY_KALEC_ORB_READY2); break;
			        case 2: DoPlaySoundToSet(m_creature, SAY_KALEC_ORB_READY3); break;
                    case 3: DoPlaySoundToSet(m_creature, SAY_KALEC_ORB_READY4); break;
		        }
            uint8 m_uiMaxDragons = 1;
            if(m_bPhase5)
                m_uiMaxDragons = 4;
            for(uint8 i=0; i<m_uiMaxDragons; ++i)
            {
                Creature* Dragon = m_creature->SummonCreature(ID_DRAGON, m_creature->GetPositionX()+urand(20,35), m_creature->GetPositionY()+urand(20,35), m_creature->GetPositionZ()+1, 0, TEMPSUMMON_CORPSE_DESPAWN, 20000);
                m_uiDragonGUID[i] = Dragon->GetGUID();
            }
            m_bBoolOrb = true;
        }else m_uiOrbTimer -= diff;

        //Shield of Blue m_uiDragonGUID[i]
        for(uint8 i=0; i<4; ++i)
        {
            if(Unit* Dragon = m_creature->GetMap()->GetUnit(m_uiDragonGUID[i]))
                if(Dragon && Dragon->HasAura(SPELL_SHIELD_OF_BLUE))
                {
                    m_uiCancelShieldTimer = 6000;
                    std::list<HostileReference *> t_list = m_creature->getThreatManager().getThreatList();
                    for(std::list<HostileReference *>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
                    {
                        Unit* TargetedPlayer = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid());  
                        if (TargetedPlayer && TargetedPlayer->GetTypeId() == TYPEID_PLAYER && TargetedPlayer->IsWithinDistInMap(Dragon, 15) && !TargetedPlayer->HasAura(AURA_BLUESHIELD))
                            TargetedPlayer->CastSpell(TargetedPlayer,AURA_BLUESHIELD,true);
                    }
                }
        }

        if(m_uiCancelShieldTimer < diff)
        {
            std::list<HostileReference *> t_list = m_creature->getThreatManager().getThreatList();
            for(std::list<HostileReference *>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
            {
                Unit *ShieldedPlayer1 = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid());
                if (ShieldedPlayer1 && ShieldedPlayer1->GetTypeId() == TYPEID_PLAYER && ShieldedPlayer1->HasAura(AURA_BLUESHIELD))
                {
                    ShieldedPlayer1->RemoveAurasDueToSpell(AURA_BLUESHIELD);
                } 
            }
            m_uiCancelShieldTimer = 300000;
        }else m_uiCancelShieldTimer -= diff;

        //Kalecgos and Anvena Event
        if((m_uiKalecgosAnvenaTimer < diff) && m_bIsAnvena)
        {
            switch(m_uiKalecgosAnvenaCount)
            {
                case 0:
                DoPlaySoundToSet(m_creature, SAY_KALECGOS_AWAKEN); m_uiKalecgosAnvenaTimer = 5000; break;
                case 1:
                DoPlaySoundToSet(m_creature, SAY_ANVEENA_IMPRISONED); m_uiKalecgosAnvenaTimer = 3000; break;
                case 2:
                DoPlaySoundToSet(m_creature, SAY_KALECGOS_LETGO); m_uiKalecgosAnvenaTimer = 6000; break;
                case 5:
                DoPlaySoundToSet(m_creature, SAY_ANVEENA_LOST); m_uiKalecgosAnvenaTimer = 4000; break;
                case 4:
                DoPlaySoundToSet(m_creature, SAY_KALECGOS_FOCUS); m_uiKalecgosAnvenaTimer = 8000; break;
                case 3:
                DoPlaySoundToSet(m_creature, SAY_ANVEENA_KALEC); m_uiKalecgosAnvenaTimer = 5000; break;
                case 6:
                DoPlaySoundToSet(m_creature, SAY_KALECGOS_FATE); m_uiKalecgosAnvenaTimer = 5000; break;
                case 7:
                DoPlaySoundToSet(m_creature, SAY_ANVEENA_GOODBYE); 
                m_creature->CastSpell(m_creature, SPELL_SACRIFICE_OF_ANVEENA, false);
                if(Unit* Anveena = m_creature->GetMap()->GetUnit(m_uiAnveenaGUID))
                    if(Anveena && Anveena->isAlive())
                        Anveena->SetVisibility(VISIBILITY_OFF);
                m_uiKalecgosAnvenaTimer = 5000;
                break;
                case 9:
                DoPlaySoundToSet(m_creature, SAY_KALECGOS_GOODBYE); ; m_bIsAnvena = false; break;
                case 8:
                DoPlaySoundToSet(m_creature, SAY_KALECGOS_ENCOURAGE); m_uiKalecgosAnvenaTimer = 14000; break;         
            }
            ++m_uiKalecgosAnvenaCount;
        }m_uiKalecgosAnvenaTimer -= diff;

        //Kalecgos Event
        if((m_uiKalecgosTimer < diff) && !m_bIsKalecgosSpawned)
        {
            DoPlaySoundToSet(m_creature, SAY_KALECGOS_JOIN);
            float x, y, z;
            m_creature->GetClosePoint(x, y, z, m_creature->GetObjectBoundingRadius(), 15.0f, urand(0, 6));
            if(Creature* cKalecgos = m_creature->SummonCreature(ID_KALECGOS, x, y, z, 0.686f, TEMPSUMMON_TIMED_DESPAWN, 600000))
            {
                m_uiKalecgosGUID = cKalecgos->GetGUID();
                cKalecgos->setFaction(35);
                cKalecgos->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
            //Kalecgos need to start shhooting arcane bolt into Kiljaeden
            //Dragon->AI()->AttackStart(m_creature);
            }
            m_bIsKalecgosSpawned = true;
        }m_uiKalecgosTimer -= diff;

        //Shield Orb At Start each phases
        if(m_uiShieldOrbTimer < diff && !m_bPhase5)
        {
            uint8 l=1;
            if(m_bPhase3)
                l=2;
            if(m_bPhase4)
                l=3;
            for(uint8 k=0; k<l; ++k)
            {
                Creature* ShieldOrb = m_creature->SummonCreature(ID_SHIELDORB, m_creature->GetPositionX()+urand(1,15), m_creature->GetPositionY()+urand(1,15), m_creature->GetPositionZ()+10, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
                if(ShieldOrb)
                    ShieldOrb->AI()->AttackStart(m_creature->getVictim()); 
            }
            m_uiShieldOrbTimer = 50000; 
        }else m_uiShieldOrbTimer -= diff;

        //Sinister Reflects Attack
        if(m_uiSinnisterCastTimer < diff)
        {
            uint8 m_uiSinisterCount = 0;
            if(m_bPhase3)
                m_uiSinisterCount = 4;
            if(m_bPhase4)
                m_uiSinisterCount = 8;
            if(m_bPhase5)
                m_uiSinisterCount = 12;
            for(uint8 i=0; i<m_uiSinisterCount; ++i)
                if(Unit* Sinister = m_creature->GetMap()->GetUnit(m_uiSinisterGUID[i][0]))
					if(Sinister->isAlive())
						if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
							Sinister->CastSpell(target, m_uiSinisterGUID[i][1], true);

            m_uiSinnisterCastTimer = urand(8000,16000);
        }else m_uiSinnisterCastTimer -= diff;

        //Phase4
        if((m_uiAramageddonTimer < diff) && m_bPhase4)
        {
            uint8 h=3;
            if(m_bPhase5)
                h=5;
            if(!m_bPhase5 && m_bDarknessOfSoulsCasting)
                h=0;
            
            for(uint8 i=0; i<h; ++i)
                if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
                    Creature* Armagedon = m_creature->SummonCreature(ID_ARMAGEDON, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 15000);

            m_uiAramageddonTimer = urand(20000,30000);
        }else m_uiAramageddonTimer -= diff;

        //ShadowSpike Explosions
        if((m_uiShadowSpikeEndsTimer < diff) && m_bShadowSpikeEnds && m_bPhase3)
        {
            if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
            {
                if(Creature* cShadowSpike = m_creature->SummonCreature(ID_SHADOWSPIKE, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 6000))
                {
                    cShadowSpike->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    cShadowSpike->setFaction(14);
                }
                //target->CastSpell(target, SPELL_SHADOWSPIKE_EXP, false);
            }
            ++m_uiSpikesCount;
            if(m_uiSpikesCount > 9)
                m_bShadowSpikeEnds = false;
            m_uiShadowSpikeEndsTimer = 3000;
        }else m_uiShadowSpikeEndsTimer -= diff;

        if(m_bShadowSpikeEnds)
            return;

        if(m_uiDarknessExplosionTimer < diff && m_bDarknessOfSoulsCasting)
        {
            //m_creature->CastSpell(m_creature->getVictim(), SPELL_DARKNESS_EXPLOSION, true);
            m_bDarknessOfSoulsCasting = false;
            m_uiDarknessExplosionTimer = 600000;
            m_uiDarknessOfSoulsTimer = 60000;
            m_uiFireBloomTimer = 25000;
            if(m_bPhase5)
                m_uiDarknessOfSoulsTimer = 35000;
        }else m_uiDarknessExplosionTimer -= diff;

        if(m_bDarknessOfSoulsCasting)
            return;

        if(m_uiDarknessOfSoulsTimer < diff && m_bPhase3)
        {
            switch (rand()%3)
		        {
			        case 0: DoPlaySoundToSet(m_creature, SAY_KJ_DARKNESS1); break;
			        case 1: DoPlaySoundToSet(m_creature, SAY_KJ_DARKNESS2); break;
			        case 2: DoPlaySoundToSet(m_creature, SAY_KJ_DARKNESS3); break;
		        }
            m_creature->CastSpell(m_creature, SPELL_DARKNESS_OF_SOULS, false);
            m_bDarknessOfSoulsCasting = true;
            m_uiDarknessExplosionTimer = 8000;
        }else m_uiDarknessOfSoulsTimer -= diff;

        //Phases
        if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) <= 85) && !m_bPhase3)
        {      
            DoPlaySoundToSet(m_creature, SAY_KJ_PHASE3);
            if(Unit* victim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) 
                if (victim && (victim->GetTypeId() == TYPEID_PLAYER))
                    Sinister(((Player*)victim),0,4);

            //Start Timerow  Dochodzacych w 3 Fazie
            m_uiFlameDartTimer         = 20000;
            m_uiSinnisterCastTimer     = 10000;
            m_uiShadowSpikeTimer       = 30000;
            m_uiFlameDartTimer         = 40000;
            m_uiDarknessOfSoulsTimer   = 60000;
            m_bShadowSpikeEnds         = false;
            m_bDarknessOfSoulsCasting  = false;
            m_bPhase3 = true;
            //DragonsTimer
            m_uiOrbTimer = 35000;
            m_bBoolOrb = false;
        }

        if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) <= 55) && !m_bPhase4)
        {
            DoPlaySoundToSet(m_creature, SAY_KJ_PHASE4);
            if(Unit* victim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) 
                if (victim && (victim->GetTypeId() == TYPEID_PLAYER))
                    Sinister(((Player*)victim),4,8);

            //Start Timerow  Dochodzacych w 4 Fazie
            m_uiFlameDartTimer         = 20000;
            m_uiAramageddonTimer       = 2000;  //100% ok
            m_bPhase4 = true;
            m_uiDarknessOfSoulsTimer   = 60000;
            //DragonsTimer
            m_uiOrbTimer = 35000;
            m_bBoolOrb = false;
        }

        if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) <= 25) && !m_bPhase5)
        {
            DoPlaySoundToSet(m_creature, SAY_KJ_PHASE5);
            if(Unit* victim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) 
                if (victim && (victim->GetTypeId() == TYPEID_PLAYER))
                    Sinister(((Player*)victim),8,12);
            //Start Timerow  Dochodzacych w 5 Fazie
            m_uiAramageddonTimer = urand(20000,30000);
            m_uiFlameDartTimer = 20000;
            m_uiShadowSpikeTimer = 1000;
            m_uiDarknessOfSoulsTimer   = 60000;
            m_bPhase5 = true;
            //DragonsTimer
            m_uiOrbTimer = 35000;
            m_bBoolOrb = false;
            //Kalecgos and Anvena Event
            m_uiKalecgosAnvenaTimer = 20000;
            m_bIsAnvena = true;
            m_uiKalecgosAnvenaCount = 0;

            if(Creature* cAnveena = m_creature->SummonCreature(ID_ANVEENA, m_creature->GetPositionX()+urand(20,30), m_creature->GetPositionY()+urand(20,30), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 120000))
            {
                m_uiAnveenaGUID = cAnveena->GetGUID();
                cAnveena->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                cAnveena->setFaction(35);
            }
        }

        //Phase3
        if(m_bPhase3)
        {
            if(m_uiShadowSpikeTimer < diff)
            {
                //DoCast(m_creature->getVictim(), SPELL_SHADOWSPIKE);
                m_bShadowSpikeEnds         = true;
                m_uiShadowSpikeEndsTimer    = 500;
                m_uiSpikesCount             = 0;
                m_uiShadowSpikeTimer        = urand(65000,95000);
            }else m_uiShadowSpikeTimer -= diff;

            if(m_uiFlameDartTimer < diff)
            {
                DoCast(m_creature->getVictim(), SPELL_FLAMEDARTS);
                m_uiFlameDartTimer = urand(41000,63000);
            }else m_uiFlameDartTimer -= diff;
        }

        //Phase2
        if(m_uiLegionLightingTimer < diff)
        {
            DoCast(m_creature->getVictim(), SPELL_LEGION_LIGHTING);
            m_uiLegionLightingTimer = urand(18000,26000);
        }else m_uiLegionLightingTimer -= diff;

        if(m_uiFireBloomTimer < diff)
        {
            for(uint8 i=0; i<5; ++i)
            {
                if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
                    m_uiFireBloomTarget[i] = target->GetGUID();
                else
                    m_uiFireBloomTarget[i] = 0;
                m_uiFireBloomCount = 0;
                //DoCast(target, SPELL_FIREBLOOM, true);
            }
            m_uiFireBloomTimer = urand(34000,56000);
        }else m_uiFireBloomTimer -= diff;

        if(m_uiSoulFlyTimer < diff)
        {
            DoCast(m_creature->getVictim(), SPELL_SOULFLY);
            m_uiSoulFlyTimer = 7000;
        }else m_uiSoulFlyTimer -= diff;

        DoMeleeAttackIfReady();
    }
Example #22
0
    void UpdateAI(const uint32 uiDiff)
    {
        //Return since we have no target
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        if (m_uiPhase == PHASE_1 || m_uiPhase == PHASE_3)
        {
            //m_uiShockBlast_Timer
            if (m_uiShockBlast_Timer < uiDiff)
            {
                //Randomly used in m_uiPhases 1 and 3 on Vashj's target, it's a Shock spell doing 8325-9675 nature damage and stunning the target for 5 seconds, during which she will not attack her target but switch to the next person on the aggro list.
                DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHOCK_BLAST);

                m_uiShockBlast_Timer = urand(1000, 15000);  //random cooldown
            }else m_uiShockBlast_Timer -= uiDiff;

            //m_uiStaticCharge_Timer
            if (m_uiStaticCharge_Timer < uiDiff)
            {
                //Used on random people (only 1 person at any given time) in m_uiPhases 1 and 3, it's a debuff doing 2775 to 3225 Nature damage to the target and everybody in about 5 yards around it, every 1 seconds for 30 seconds. It can be removed by Cloak of Shadows, Iceblock, Divine Shield, etc, but not by Cleanse or Dispel Magic.
                Unit *pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);

                //cast Static Charge every 2 seconds for 20 seconds
                if (pTarget && !pTarget->HasAura(SPELL_STATIC_CHARGE_TRIGGER))
                    DoCastSpellIfCan(pTarget, SPELL_STATIC_CHARGE_TRIGGER);

                m_uiStaticCharge_Timer = urand(10000, 30000);
            }else m_uiStaticCharge_Timer -= uiDiff;

            //m_uiEntangle_Timer
            if (m_uiEntangle_Timer < uiDiff)
            {
                if (!m_bEntangle)
                {
                    //Used in m_uiPhases 1 and 3, it casts Entangling Roots on everybody in a 15 yard radius of Vashj, immobilzing them for 10 seconds and dealing 500 damage every 2 seconds. It's not a magic effect so it cannot be dispelled, but is removed by various buffs such as Cloak of Shadows or Blessing of Freedom.
                    DoCastSpellIfCan(m_creature->getVictim(), SPELL_ENTANGLE);
                    m_bEntangle = true;
                    m_uiEntangle_Timer = 10000;
                }
                else
                {
                    CastShootOrMultishot();
                    m_bEntangle = false;
                    m_uiEntangle_Timer = urand(20000, 25000);
                }
            }else m_uiEntangle_Timer -= uiDiff;

            //m_uiPhase 1
            if (m_uiPhase == PHASE_1)
            {
                //m_uiPhase 2 begins when Vashj hits 70%. She will run to the middle of her platform and surround herself in a shield making her invulerable.
                if (m_creature->GetHealthPercent() <= 70.0f)
                {
                    DoScriptText(SAY_PHASE2, m_creature);

                    if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
                    {
                        //set false, so MoveChase is not triggered in AttackStart
                        SetCombatMovement(false);

                        m_creature->GetMotionMaster()->MovementExpired();
                        m_creature->GetMotionMaster()->MovePoint(POINT_MOVE_CENTER, afMiddlePos[0], afMiddlePos[1], afMiddlePos[2]);
                    }

                    m_uiPhase = PHASE_2;
                    return;
                }
            }
            //m_uiPhase PHASE_3
            else
            {
                //m_uiSummonSporebat_Timer
                if (m_uiSummonSporebat_Timer < uiDiff)
                {
                    m_creature->SummonCreature(NPC_TOXIC_SPOREBAT,
                        afSporebatPos[0], afSporebatPos[1], afSporebatPos[2], afSporebatPos[3],
                        TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);

                    //summon sporebats faster and faster
                    if (m_uiSummonSporebat_StaticTimer > 1000)
                        m_uiSummonSporebat_StaticTimer -= 1000;

                    m_uiSummonSporebat_Timer = m_uiSummonSporebat_StaticTimer;
                }else m_uiSummonSporebat_Timer -= uiDiff;
            }

            //Melee attack
            DoMeleeAttackIfReady();

            //m_uiCheck_Timer - used to check if somebody is in melee range
            if (m_uiCheck_Timer < uiDiff)
            {
                bool bInMeleeRange = false;
                ThreatList const& tList = m_creature->getThreatManager().getThreatList();
                for (ThreatList::const_iterator itr = tList.begin();itr != tList.end(); ++itr)
                {
                    Unit* pTarget = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());

                    //if in melee range
                    if (pTarget && pTarget->IsWithinDistInMap(m_creature, ATTACK_DISTANCE))
                    {
                        bInMeleeRange = true;
                        break;
                    }
                }

                //if nobody is in melee range
                if (!bInMeleeRange)
                    CastShootOrMultishot();

                m_uiCheck_Timer = 1500;
            }else m_uiCheck_Timer -= uiDiff;
        }
        //m_uiPhase PHASE_2
        else
        {
            //m_uiForkedLightning_Timer
            if (m_uiForkedLightning_Timer < uiDiff)
            {
                //Used constantly in m_uiPhase 2, it shoots out completely randomly targeted bolts of lightning which hit everybody in a roughtly 60 degree cone in front of Vashj for 2313-2687 nature damage.
                Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);

                if (!pTarget)
                    pTarget = m_creature->getVictim();

                DoCastSpellIfCan(pTarget, SPELL_FORKED_LIGHTNING);

                m_uiForkedLightning_Timer = urand(3000, 9000);
            }else m_uiForkedLightning_Timer -= uiDiff;

            //NPC_ENCHANTED_ELEMENTAL
            if (m_uiEnchantedElemental_Timer < uiDiff)
            {
                if (Creature* pElemental = m_creature->SummonCreature(NPC_ENCHANTED_ELEMENTAL, afElementPos[m_uiEnchantedElemental_Pos][0], afElementPos[m_uiEnchantedElemental_Pos][1], afElementPos[m_uiEnchantedElemental_Pos][2], afElementPos[m_uiEnchantedElemental_Pos][3], TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000))
                    pElemental->GetMotionMaster()->MoveFollow(m_creature, 0.0f, 0.0f);

                if (m_uiEnchantedElemental_Pos == 7)
                    m_uiEnchantedElemental_Pos = 0;
                else
                    ++m_uiEnchantedElemental_Pos;

                m_uiEnchantedElemental_Timer = urand(10000, 15000);
            }else m_uiEnchantedElemental_Timer -= uiDiff;

            //NPC_TAINTED_ELEMENTAL
            if (m_uiTaintedElemental_Timer < uiDiff)
            {
                uint32 uiPos = urand(0,7);

                m_creature->SummonCreature(NPC_TAINTED_ELEMENTAL,
                    afElementPos[uiPos][0], afElementPos[uiPos][1], afElementPos[uiPos][2], afElementPos[uiPos][3],
                    TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 15000);

                m_uiTaintedElemental_Timer = 120000;
            }else m_uiTaintedElemental_Timer -= uiDiff;

            //NPC_COILFANG_ELITE
            if (m_uiCoilfangElite_Timer < uiDiff)
            {
                uint32 uiPos = urand(0,2);

                m_creature->SummonCreature(NPC_COILFANG_ELITE,
                    afCoilfangElitePos[uiPos][0], afCoilfangElitePos[uiPos][1], afCoilfangElitePos[uiPos][2], afCoilfangElitePos[uiPos][3],
                    TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 45000);

                //wowwiki says 50 seconds, bosskillers says 45
                m_uiCoilfangElite_Timer = urand(45000, 50000);
            }else m_uiCoilfangElite_Timer -= uiDiff;

            //NPC_COILFANG_STRIDER
            if (m_uiCoilfangStrider_Timer < uiDiff)
            {
                uint32 uiPos = urand(0,2);

                m_creature->SummonCreature(NPC_COILFANG_STRIDER,
                    afCoilfangStriderPos[uiPos][0], afCoilfangStriderPos[uiPos][1], afCoilfangStriderPos[uiPos][2], afCoilfangStriderPos[uiPos][3],
                    TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);

                //wowwiki says 60 seconds, bosskillers says 60-70
                m_uiCoilfangStrider_Timer = urand(60000, 70000);
            }else m_uiCoilfangStrider_Timer -= uiDiff;

            //m_uiCheck_Timer
            if (m_uiCheck_Timer < uiDiff)
            {
                //Start m_uiPhase 3
                if (m_pInstance && m_pInstance->GetData(TYPE_VASHJ_PHASE3_CHECK) == DONE)
                {
                    DoScriptText(SAY_PHASE3, m_creature);

                    //set life 50%, not correct. Must remove 5% for each generator switched off
                    m_creature->SetHealth(m_creature->GetMaxHealth()/2);

                    m_creature->RemoveAurasDueToSpell(SPELL_MAGIC_BARRIER);

                    SetCombatMovement(true);

                    //return to chase top aggro
                    if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE)
                        m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());

                    m_uiPhase = PHASE_3;
                }
                m_uiCheck_Timer = 1000;
            }else m_uiCheck_Timer -= uiDiff;
        }
    }
Example #23
0
    void UpdateAI(const uint32 diff)
    {
        advisorbase_ai::UpdateAI(diff);

        //Faking Death, don't do anything
        if (FakeDeath)
            return;

        //Return since we have no target
        if (!UpdateVictim())
            return;

        //Yell_Timer
        if (!Yell)
        {
            if (Yell_Timer <= diff)
            {
                DoScriptText(SAY_CAPERNIAN_AGGRO, me);
                Yell = true;
            } else Yell_Timer -= diff;
        }

        //Fireball_Timer
        if (Fireball_Timer <= diff)
        {
            DoCast(me->getVictim(), SPELL_CAPERNIAN_FIREBALL);
            Fireball_Timer = 4000;
        } else Fireball_Timer -= diff;

        //Conflagration_Timer
        if (Conflagration_Timer <= diff)
        {
            Unit *pTarget = NULL;
            pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0);

            if (pTarget && me->IsWithinDistInMap(pTarget, 30))
                DoCast(pTarget, SPELL_CONFLAGRATION);
            else
                DoCast(me->getVictim(), SPELL_CONFLAGRATION);

            Conflagration_Timer = 10000+rand()%5000;
        } else Conflagration_Timer -= diff;

        //ArcaneExplosion_Timer
        if (ArcaneExplosion_Timer <= diff)
        {
            bool InMeleeRange = false;
            Unit *pTarget = NULL;
            std::list<HostileReference*>& m_threatlist = me->getThreatManager().getThreatList();
            for (std::list<HostileReference*>::const_iterator i = m_threatlist.begin(); i!= m_threatlist.end(); ++i)
            {
                Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid());
                                                            //if in melee range
                if (pUnit && pUnit->IsWithinDistInMap(me, 5))
                {
                    InMeleeRange = true;
                    pTarget = pUnit;
                    break;
                }
            }

            if (InMeleeRange)
                DoCast(pTarget, SPELL_ARCANE_EXPLOSION);

            ArcaneExplosion_Timer = 4000+rand()%2000;
        } else ArcaneExplosion_Timer -= diff;

        //Do NOT deal any melee damage.
    }