Example #1
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 #2
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 #3
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;
        }
    }
Example #4
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.
                if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHOCK_BLAST) == CAST_OK)
                    m_uiShockBlast_Timer = urand(8000, 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, SPELL_STATIC_CHARGE_TRIGGER, SELECT_FLAG_PLAYER);

                //cast Static Charge every 2 seconds for 20 seconds
                if (pTarget && !pTarget->HasAura(SPELL_STATIC_CHARGE_TRIGGER) && DoCastSpellIfCan(pTarget, SPELL_STATIC_CHARGE_TRIGGER) == CAST_OK)
                    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.
                    if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_ENTANGLE) == CAST_OK)
                    {
                        m_bEntangle = true;
                        m_uiEntangle_Timer = 10000;
                    }
                }
                else
                {
                    CastShootOrMultishot(m_creature->getVictim());
                    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
            {
                // @Lorh : Mind Control (effect on 2 random target)
                if (m_uiPersuasionTimer <= uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature, SPELL_PERSUASION) == CAST_OK)
                        m_uiPersuasionTimer = 45000;
                }
                else
                    m_uiPersuasionTimer -= uiDiff;

                //@Lorh : Custom increase sporebat
                if (m_uiAddSporebat < uiDiff)
                {
                    if (m_uiCountSporebat < 4)		//Stop at 4 sporebat summoned. After 4mn , m_uiSummonSporebat_Timer manage soft enrage
                        m_uiCountSporebat++;

                    //Switch case, more easy to adapt timer if needed
                    switch(m_uiCountSporebat)
                    {
                    case 2:									// 2 sporebat at 1mn
                        m_uiAddSporebat = 130000;
                        break;
                    case 3:									// 3 sporebat at 3mn10
                        m_uiAddSporebat = 50000;
                        break;
                    default:								// 4 sporebat at 4mn, go enrage
                        m_uiAddSporebat = 80000;
                        break;
                    }
                }
                else
                    m_uiAddSporebat -= uiDiff;

                // Summon Sporebat timer
                if (m_uiSummonSporebat_Timer < uiDiff)
                {
                    for (uint8 summonSporebat = 0; summonSporebat < m_uiCountSporebat; summonSporebat++)
                        m_creature->SummonCreature(NPC_TOXIC_SPOREBAT, afSporebatPos[0], afSporebatPos[1], afSporebatPos[2], frand(-6.0f, 6.0f), TEMPSUMMON_DEAD_DESPAWN, 5000);

                    if (m_uiSummonSporebat_StaticTimer <= 4000)
                        m_uiSummonSporebat_StaticTimer = 4000;		//This case happened after 4mn, soft enrage start
                    else
                        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)
            {
                //if nobody is in melee range
                if (!m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, uint32(0), SELECT_FLAG_IN_MELEE_RANGE))
                    CastShootOrMultishot(m_creature->getVictim());

                m_uiCheck_Timer = 3000;
            }
            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();

                if (DoCastSpellIfCan(pTarget, SPELL_FORKED_LIGHTNING) == CAST_OK)
                    m_uiForkedLightning_Timer = urand(2000, 8000);
            }
            else
                m_uiForkedLightning_Timer -= uiDiff;

            //NPC_ENCHANTED_ELEMENTAL
            if (m_uiEnchantedElemental_Timer < uiDiff)
            {
                uint32 uiPos = urand(0, 7);

                if (Creature* pElemental = m_creature->SummonCreature(NPC_ENCHANTED_ELEMENTAL,
                                           afElementPos[uiPos][0], afElementPos[uiPos][1], afElementPos[uiPos][2], afElementPos[uiPos][3],
                                           TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000))
                    pElemental->GetMotionMaster()->MoveFollow(m_creature, 0.0f, 0.0f);

                switch (m_uiShieldGeneratorDown)
                {
                case 1:
                    m_uiEnchantedElemental_Timer = urand(5000, 9000);
                    break;
                case 2:
                    m_uiEnchantedElemental_Timer = urand(5000, 8000);
                    break;
                case 3:
                    m_uiEnchantedElemental_Timer = urand(5000, 7000);
                    break;
                case 4:
                    m_uiEnchantedElemental_Timer = urand(5000, 6000);
                    break;
                default:
                    m_uiEnchantedElemental_Timer = urand(5000, 10000);
                    break;
                }

            }
            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, 60000);

                m_uiTaintedElemental_Timer = 120000;
            }
            else
                m_uiTaintedElemental_Timer -= uiDiff;

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

                if (Creature* pElite = m_creature->SummonCreature(NPC_COILFANG_ELITE,
                                       afElementPos[uiPos][0], afElementPos[uiPos][1], afElementPos[uiPos][2], afElementPos[uiPos][3],
                                       TEMPSUMMON_TIMED_OOC_OR_DEAD_DESPAWN, 15000)) // @Lorh : I change the flag to avoid that he despawn after 45sec
                    pElite->GetMotionMaster()->MovePoint(POINT_MOVE_FLOOR, afFloorPoint[uiPos][0], afFloorPoint[uiPos][1], afFloorPoint[uiPos][2]);

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

                if (Creature* pStrider = m_creature->SummonCreature(NPC_COILFANG_STRIDER,
                                         afElementPos[uiPos][0], afElementPos[uiPos][1], afElementPos[uiPos][2], afElementPos[uiPos][3],
                                         TEMPSUMMON_TIMED_OOC_OR_CORPSE_DESPAWN, 8000)) //@Lorh : I changed the flag, to avoid that aoe fear take effect after death
                    pStrider->GetMotionMaster()->MovePoint(POINT_MOVE_FLOOR, afFloorPoint[uiPos][0], afFloorPoint[uiPos][1], afFloorPoint[uiPos][2]);

                //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);

                    SetCombatMovement(true);
                    //@Lorh : Reset Aggro
                    DoResetThreat();

                    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;
        }
    }