Beispiel #1
0
void PlayerbotRogueAI::DoNextCombatManeuver(Unit *pTarget)
{
    if (!pTarget || pTarget->isDead()) return;
    PlayerbotAI *ai = GetAI();
    if (!ai) return;
    Player *m_bot = GetPlayerBot();
    if (!m_bot || m_bot->isDead()) return;
    Unit *pVictim = pTarget->getVictim();
    Unit *m_tank = FindMainTankInRaid(GetMaster());
    if (!m_tank && m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup()) { FindMainTankInRaid(m_bot); }
    if (!m_tank) { m_tank = m_bot; }
    uint32 masterHP = GetMaster()->GetHealth()*100 / GetMaster()->GetMaxHealth();
    float pDist = m_bot->GetDistance(pTarget);
    uint8 pThreat = GetThreatPercent(pTarget);

    /*switch (ai->GetScenarioType()) {
        case SCENARIO_DUEL: 
            ((CastSpell(BACKSTAB)) ||
            (pTarget->IsNonMeleeSpellCasted(true) && CastSpell(KICK)) ||
            ((GetPlayerBot()->GetComboPoints()==5) && CastSpell(SLICE_DICE)) ||
            (CastSpell(SINISTER_STRIKE)));
            return;
    }*/
    #pragma region Choose Target
    // Choose actions accoring to talents (ROGUE is always MELEE DPS)
    m_role = BOT_ROLE_DPS_MELEE;

    // if i am under attack and if i am not tank or offtank: change target if needed
    if (m_tank->GetGUID() != m_bot->GetGUID() && isUnderAttack() ) 
    {
        // Keep hitting but reduce threat
        if (CastSpell(FEINT,m_bot)) { return; }
        else if (CastSpell(TRICKS_OF_THE_TRADE,m_tank)) { return; }
        else if (CastSpell(VANISH,m_bot)) { return; }
        //else if (m_bot->getRace() == (uint8) RACE_NIGHTELF && CastSpell(R_SHADOWMELD,m_bot)) { return; }
        else //I cannot reduce threat so
        {
            if (pVictim && pVictim->GetGUID() == m_bot->GetGUID() && pDist <= 2) {  } // My target is almost up to me, no need to search
            else //Have to select nearest target
            {
                Unit *curAtt = GetNearestAttackerOf(m_bot);
                if (curAtt && curAtt->GetGUID() != pTarget->GetGUID())
                {
                    m_bot->SetSelection(curAtt->GetGUID());
                    //ai->AddLootGUID(curAtt->GetGUID());
                    DoNextCombatManeuver(curAtt); //Restart new update to get variables fixed..
                    return; 
                }
            }
            //my target is attacking me
        }
    }
    #pragma endregion

    // wait until we actually reach our target b4 we actually do anything
    /*if (m_bot->GetDistance(pTarget)>10.0 && 
        !m_bot->HasAura(STEALTH) &&
        !m_bot->isInCombat() && CastSpell(STEALTH)) 
    { return; }*/

    TakePosition(pTarget);

    // If there's a cast stop
    if (m_bot->hasUnitState(UNIT_STAT_CASTING)) { return; }

    // wait until we actually reach our target b4 we actually do anything
    if (GetPlayerBot()->GetDistance(pTarget)>10.0 && 
        !HasAuraName(GetPlayerBot(),STEALTH) &&
        !GetPlayerBot()->isInCombat() && CastSpell(STEALTH)) 
    { return; }

    //Buff
    if (CastSpell(PREMEDITATION,m_bot)) { return; }

    //PROTECT UP
    if (m_tank->GetGUID() != m_bot->GetGUID() && pVictim && pVictim->GetGUID() == m_bot->GetGUID() )
    {
        if (CastSpell(FEINT,m_bot)) { return; }
        if (CastSpell(TRICKS_OF_THE_TRADE,m_tank)) { return; }
        if (CastSpell(VANISH,m_bot)) { return; }
    }
    if (isUnderAttack() && pDist <= MELEE_RANGE && ai->GetHealthPercent() <= 85 && CastSpell(EVASION, m_bot)) { } //no GCD
    if (ai->GetHealthPercent() <= 55 && CastSpell(CLOAK_OF_SHADOWS, m_bot)) { return; }
    if (isUnderAttack() && ai->GetHealthPercent() <= 65 && CastSpell(GOUGE, m_bot)) { return; }
    if (isUnderAttack() && ai->GetHealthPercent() <= 45 && CastSpell(BLIND, m_bot)) { return; }
    if (m_bot->getRace() == (uint8) RACE_DWARF && ai->GetHealthPercent() < 75 && CastSpell(R_STONEFORM,m_bot)) { } //no gcd
    if (m_bot->getRace() == (uint8) RACE_DRAENEI && ai->GetHealthPercent() < 55 && CastSpell(R_GIFT_OF_NAARU,m_bot)) { return; } //no Gcd, but has cast
    if (m_bot->getRace() == (uint8) RACE_TAUREN && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return; } //no gcd but is cast

    //Break spells
    if (m_bot->getRace() == (uint8) RACE_BLOODELF && pDist < 8 && (pTarget->IsNonMeleeSpellCasted(true) || ai->GetManaPercent() < 40) && CastSpell(R_ARCANE_TORRENT, pTarget)) { } //no gcd
    else if (pTarget->IsNonMeleeSpellCasted(true) && CastSpell(KICK, pTarget)) { return; }
    else if (pTarget->IsNonMeleeSpellCasted(true) && CastSpell(GOUGE, pTarget)) { return; }
    else if (pTarget->IsNonMeleeSpellCasted(true) && m_bot->GetComboPoints() >= 1 && CastSpell(KIDNEY_SHOT, pTarget)) { return; }

    // If at threat limit, try to reduce threat
    if (pThreat > threatThreshold && m_tank->GetGUID() != m_bot->GetGUID() && !isUnderAttack())
    {
        if (m_tank->getVictim() && m_tank->getVictim()->GetGUID() != pTarget->GetGUID()) // I am attacking wrong target!!
        {
            m_bot->SetSelection(m_tank->getVictim()->GetGUID());
            return;
        }
        else  
        {
            if (CastSpell(FEINT,m_bot)) { return; } //Lets see if we can manage
            else if (CastSpell(TRICKS_OF_THE_TRADE,m_tank)) { return; }
            else { return; } //use no spells and wait threat to be reduced
        }
    }

    //Transfer threat
    if (m_tank->GetGUID() != m_bot->GetGUID() && CastSpell(TRICKS_OF_THE_TRADE,m_tank)) { return; }

    //Urgent DPS
    if ((m_bot->HasAura(STEALTH) || m_bot->HasAura(VANISH))&& CastSpell(CHEAP_SHOT,pTarget)) { return; }

    //DPS UP
    if (m_bot->getRace() == (uint8) RACE_TROLL && CastSpell(R_BERSERKING,m_bot)) {} //no GCD
    if (m_bot->getRace() == (uint8) RACE_ORC && CastSpell(R_BLOOD_FURY,m_bot)) {} //no GCD
    if (CastSpell(COLD_BLOOD,m_bot)) { } //no gcd
    if (CastSpell(HUNGER_FOR_BLOOD,m_bot)) { return; }
    if (CastSpell(BLADE_FLURRY,m_bot)) { return; }
    if (ai->GetEnergyAmount() < 20 && CastSpell(ADRENALINE_RUSH,m_bot)) { return; }
    if (CastSpell(SHADOW_DANCE,m_bot)) { return; }
    if (CastSpell(DISMANTLE,pTarget)) { return; }
    if (CastSpell(PREPARATION,m_bot)) { return; }


    if (m_bot->GetComboPoints() < 5)
    {
        if (CastSpell(RIPOSTE,pTarget)) { return; }
        if (CastSpell(KILLING_SPREE,m_bot,1,0,1)) { return; } // KILLING SPREE works great on 1 mob
        if (isUnderAttack(m_tank,3) && CastSpell(FAN_OF_KNIVES,pTarget)) { return; }
        if (BACKSTAB && !pTarget->HasInArc(M_PI,m_bot)) { if (CastSpell(BACKSTAB, pTarget)) { return; } }
        else if (CastSpell(MUTILATE, pTarget)) { return; }
        if (CastSpell(SINISTER_STRIKE,pTarget)) { return; }
        if (CastSpell(HEMORRHAGE,pTarget)) { return; }
        if (CastSpell(GHOSTLY_STRIKE,pTarget)) { return; }        
    }
    else 
    {
        if (ai->GetHealthPercent(*pTarget) > 30 && !m_bot->HasAura(SLICE_AND_DICE) && CastSpell(SLICE_AND_DICE)) { return; }
        if (ai->GetHealthPercent(*pTarget) < 20 && CastSpell(EVISCERATE)) { return; }
        if (!pTarget->HasAura(RUPTURE) && CastSpell(RUPTURE)) { return; }
        if (CastSpell(EVISCERATE)) { return; } // default if all else fails
    }
   
   
} //end DoNextCombatManeuver
Beispiel #2
0
    void UpdateAI(const uint32 diff)
    {
        if (!UpdateVictim())
            return;

        if(StormCount)
        {
            Unit* target = Unit::GetUnit(*m_creature, CloudGUID);
            if(!target || !target->isAlive())
            {
                EnterEvadeMode();
                return;
            }
            else if(Unit* Cyclone = Unit::GetUnit(*m_creature, CycloneGUID))
                Cyclone->CastSpell(target, 25160, true); // keep casting or...

            if(StormSequenceTimer < diff) {
                HandleStormSequence(target);
            }else StormSequenceTimer -= diff;
            return;
        }

        if (Enrage_Timer < diff) {
            DoYell(SAY_ONENRAGE, LANG_UNIVERSAL, NULL);
            DoPlaySoundToSet(m_creature, SOUND_ONENRAGE);
            m_creature->CastSpell(m_creature, SPELL_BERSERK, true);
            Enrage_Timer = 600000;
        }else Enrage_Timer -= diff;

        if (StaticDisruption_Timer < diff) {
            Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1);
            if(!target) target = m_creature->getVictim();
            TargetGUID = target->GetGUID();
            m_creature->CastSpell(target, SPELL_STATIC_DISRUPTION, false);
            m_creature->SetInFront(m_creature->getVictim());
            StaticDisruption_Timer = (10+rand()%8)*1000; // < 20s

            /*float dist = m_creature->GetDistance(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ());
            if (dist < 5.0f) dist = 5.0f;
            SDisruptAOEVisual_Timer = 1000 + floor(dist / 30 * 1000.0f);*/
        }else StaticDisruption_Timer -= diff;

        if (GustOfWind_Timer < diff) {
            Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1);
            if(!target) target = m_creature->getVictim();
            DoCast(target, SPELL_GUST_OF_WIND);
            GustOfWind_Timer = (20+rand()%10)*1000; //20 to 30 seconds(bosskillers)
        } else GustOfWind_Timer -= diff;

        if (CallLighting_Timer < diff) {
            DoCast(m_creature->getVictim(), SPELL_CALL_LIGHTNING);
            CallLighting_Timer = (12 + rand()%5)*1000; //totaly random timer. can't find any info on this
        } else CallLighting_Timer -= diff;

        if (!isRaining && ElectricalStorm_Timer < 8000 + rand()%5000) {
            SetWeather(WEATHER_STATE_HEAVY_RAIN, 0.9999f);
            isRaining = true;
        }

        if (ElectricalStorm_Timer < diff) {
            Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, 50, true);
            if(!target)
            {
                EnterEvadeMode();
                return;
            }
            target->CastSpell(target, 44007, true);//cloud visual
            m_creature->CastSpell(target, SPELL_ELECTRICAL_STORM, false);//storm cyclon + visual
            float x,y,z;
            target->GetPosition(x,y,z);
            if (target)
            {
                target->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING);
                target->SendMonsterMove(x,y,m_creature->GetPositionZ()+15,0);
            }
            Unit *Cloud = m_creature->SummonTrigger(x, y, m_creature->GetPositionZ()+16, 0, 15000);
            if(Cloud)
            {
                CloudGUID = Cloud->GetGUID();
                Cloud->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING);
                Cloud->StopMoving();
                Cloud->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f);
                Cloud->setFaction(35);
                Cloud->SetMaxHealth(9999999);
                Cloud->SetHealth(9999999);
                Cloud->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
            }
            ElectricalStorm_Timer = 60000; //60 seconds(bosskillers)
            StormCount = 1;
            StormSequenceTimer = 0;
        } else ElectricalStorm_Timer -= diff;

        if (SummonEagles_Timer < diff)
        {
            DoYell(SAY_ONSUMMON, LANG_UNIVERSAL, NULL);
            DoPlaySoundToSet(m_creature, SOUND_ONSUMMON);

            float x, y, z;
            m_creature->GetPosition(x, y, z);

            for (uint8 i = 0; i < 8; i++)
            {
                Unit* bird = Unit::GetUnit(*m_creature,BirdGUIDs[i]);
                if(!bird)//they despawned on die
                {
                    if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
                    {
                        x = target->GetPositionX() + 10 - rand()%20;
                        y = target->GetPositionY() + 10 - rand()%20;
                        z = target->GetPositionZ() + 6 + rand()%5 + 10;
                        if(z > 95) z = 95 - rand()%5;
                    }
                    Creature *pCreature = m_creature->SummonCreature(MOB_SOARING_EAGLE, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
                    if (pCreature)
                    {
                        pCreature->AddThreat(m_creature->getVictim(), 1.0f);
                        pCreature->AI()->AttackStart(m_creature->getVictim());
                        BirdGUIDs[i] = pCreature->GetGUID();
                    }
                }
            }
            SummonEagles_Timer = 999999;
        } else SummonEagles_Timer -= diff;

        DoMeleeAttackIfReady();
    }
void PlayerbotMageAI::DoNextCombatManeuver(Unit *pTarget)
{
    if (!pTarget || pTarget->isDead()) return;
    PlayerbotAI *ai = GetAI();
    if (!ai) return;
    Player *m_bot = GetPlayerBot();
    if (!m_bot || m_bot->isDead()) return;
    Unit *pVictim = pTarget->getVictim();
    Unit *m_tank = FindMainTankInRaid(GetMaster());
    if (!m_tank && m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup()) { FindMainTankInRaid(m_bot); }
    if (!m_tank) { m_tank = m_bot; }
    uint32 masterHP = GetMaster()->GetHealth()*100 / GetMaster()->GetMaxHealth();
    float pDist = m_bot->GetDistance(pTarget);
    uint8 pThreat = GetThreatPercent(pTarget);

    #pragma region Choose Actions
    // Choose actions accoring to talents (MAGE is always ranged dps)
    m_role = BOT_ROLE_DPS_RANGED;

    // if i am under attack and if i am not tank or offtank: change target if needed
    if (isUnderAttack())
    {
        // Keep hitting but reduce threat
        //else if (m_bot->getRace() == (uint8) RACE_NIGHTELF && CastSpell(R_SHADOWMELD,m_bot)) { return; }
            if (pVictim && pVictim->GetGUID() == m_bot->GetGUID() && pDist <= 2) {  } // My target is almost up to me, no need to search
            else //Have to select nearest target
            {
                Unit *curAtt = GetNearestAttackerOf(m_bot);
                if (curAtt && curAtt->GetGUID() != pTarget->GetGUID())
                {
                    m_bot->SetSelection(curAtt->GetGUID());
                    DoNextCombatManeuver(curAtt); //Restart new update to get variables fixed..
                    return;
                }
            }
            //my target is attacking me
    }
    #pragma endregion

    TakePosition(pTarget);
    // If there's a cast stop
    if (m_bot->HasUnitState(UNIT_STAT_CASTING)) { return; }

    if (DoSupportRaid(m_bot,30,0,0,0,1,1)) { return; }

    if (m_tank->GetGUID() != m_bot->GetGUID() && pVictim && pVictim->GetGUID() == m_bot->GetGUID() )
    {
        //if (CastSpell(INVISIBILITY, m_bot)) { return; }
        if (ai->GetHealthPercent(*pTarget) > 50 && CastSpell(POLYMORPH)) { return; }
        //if (m_bot->getRace() == (uint8) RACE_NIGHTELF && isUnderAttack() && CastSpell(R_SHADOWMELD, m_bot)) { return; }
    }
    if (isUnderAttack() && pDist > 5 && CastSpell(FROST_NOVA, pTarget)) { return; }
    if (DEEP_FREEZE && pTarget->isFrozen() && CastSpell(DEEP_FREEZE,pTarget)) { return; }
    if (isUnderAttack() && CastSpell(DRAGONS_BREATH, pTarget)) { return; }
    if ((isUnderAttack() || ai->GetHealthPercent() < 75 && !HasAuraName(m_bot, MANA_SHIELD))  && ai->GetManaPercent() > 40 && CastSpell(MANA_SHIELD,m_bot)) { return; }
    if (m_bot->getRace() == (uint8) RACE_DWARF && ai->GetHealthPercent() < 75 && CastSpell(R_STONEFORM,m_bot)) { } //no gcd
    if (m_bot->getRace() == (uint8) RACE_DRAENEI && ai->GetHealthPercent() < 55 && CastSpell(R_GIFT_OF_NAARU,m_bot)) { return; } //no Gcd, but has cast
    if (m_bot->getRace() == (uint8) RACE_TAUREN && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return; } //no gcd but is cast
    if ((ai->GetHealthPercent() < 65 || ai->GetManaPercent() < 5) && CastSpell(ICE_BLOCK,m_bot)) { return; }
    if (isUnderAttack() && CastSpell(ICE_BARRIER, pTarget)) { return; }
    if (ai->GetManaPercent() < 30 && CastSpell (EVOCATION, m_bot)) { return; }


    //Break spells
    if (m_bot->getRace() == (uint8) RACE_BLOODELF && pDist < 8 && (pTarget->IsNonMeleeSpellCasted(true) || ai->GetManaPercent() < 40) && CastSpell(R_ARCANE_TORRENT, pTarget)) { } //no gcd
    else if (pThreat < threatThreshold && pTarget->IsNonMeleeSpellCasted(true) && CastSpell(COUNTER_SPELL, pTarget)) { return; } //High threat
	if (!m_bot->HasAura(MOLTEN_ARMOR) && CastSpell(MOLTEN_ARMOR,m_bot)) { return; }

    if (ai->GetHealthPercent(*pTarget) > 96) { return; } // dont dps too early

    //Catch
    if (pTarget->HasUnitMovementFlag(UNIT_FLAG_FLEEING))
    {
        if (CastSpell(FROST_NOVA,pTarget)) return;
        if (CastSpell(FROSTBOLT,pTarget)) return;
    }

    // If at threat limit, try to reduce threat
    if (pThreat > threatThreshold && m_tank->GetGUID() != m_bot->GetGUID() && !isUnderAttack())
    {
        if (m_tank->getVictim() && m_tank->getVictim()->GetGUID() != pTarget->GetGUID()) // I am attacking wrong target!!
        {
            m_bot->SetSelection(m_tank->getVictim()->GetGUID());
            return;
        }
        else
        {
            if (CastSpell(INVISIBILITY,m_bot)) { return; } //Lets see if we can manage
            else if (m_bot->FindCurrentSpellBySpellId(SHOOT)) { m_bot->InterruptNonMeleeSpells( true, SHOOT ); return; } //Disable wand
            else { return; } //use no spells and wait threat to be reduced
        }
    }


    // buff up
    if (CastSpell(ICY_VEINS,m_bot)) {} //nogcd
    if (m_bot->getRace() == (uint8) RACE_TROLL && CastSpell(R_BERSERKING,m_bot)) {} //no GCD
    if (m_bot->getRace() == (uint8) RACE_ORC && CastSpell(R_BLOOD_FURY,m_bot)) {} //no GCD
    if (CastSpell(POM,m_bot)) {} //nogcd

	if (TALENT_ARCANE)
	{
		if (CastSpell(ARCANE_POWER,m_bot)) {} //nogcd
		if (CastSpell(MIRROR_IMAGE,m_bot)) { return; }
		//AOE
		if (isUnderAttack(m_tank,5))
		{
			if (CastSpell(BLIZZARD,pTarget)) { return; }
		}
		//DPS
		if (ARCANE_BLAST)
        {
            Aura *abaura = m_bot->GetAura(P_ARCANE_BLAST);
            if (abaura && abaura->GetStackAmount() >= 3)
			{
				if (m_bot->HasAura(P_MISSILE_BARRAGE) && CastSpell(ARCANE_MISSILES,pTarget)) { return; }
				else if (CastSpell(ARCANE_BARRAGE,pTarget)) { return; }
			}
        }
        if (CastSpell(ARCANE_BARRAGE,pTarget) ) { return; }

	}
	if (TALENT_FIRE)
	{
		if (CastSpell(COMBUSTION,m_bot)) { } //nogcd
		if (CastSpell(MIRROR_IMAGE,m_bot)) { return; }

		//AOE
		if (isUnderAttack(m_tank,5))
		{
			if (CastSpell(FLAMESTRIKE,pTarget)) { return; }
			if (CastSpell(BLAST_WAVE,pTarget)) { return; }
			if (CastSpell(LIVING_BOMB,pTarget)) { return; }
			if (CastSpell(DRAGONS_BREATH,pTarget)) { return; }
		}

		//DPS
		if (m_bot->HasAura(P_HOT_STREAK) && CastSpell(PYROBLAST,pTarget)) { return; }
		if (!pTarget->HasAura(LIVING_BOMB,m_bot->GetGUID()) && CastSpell(LIVING_BOMB,pTarget)) { return; }
		//if (!pTarget->HasAura(IMP_SCORCH) && CastSpell(SCORCH,pTarget)) { return; }
		if (CastSpell(FIREBALL,pTarget)) { return; }
	}
	if (TALENT_FROST)
	{
		if (CastSpell(MIRROR_IMAGE,m_bot)) { return; }
        if (CastSpell(WATER_ELEMENTAL,m_bot)) { return; }

        uint64 pet_guid = m_bot->GetPetGUID();
        if (pet_guid>0){
            Pet* pet = ObjectAccessor::GetPet(*m_bot, pet_guid);
            Unit *unit = ObjectAccessor::GetUnit(*m_bot, pet_guid);
            if (unit!=NULL){
				if (!unit->isInCombat()) {
                    m_bot->GetSession()->HandlePetActionHelper(unit, pet_guid, COMMAND_ATTACK, ACT_COMMAND, pTarget->GetGUID());
				}
            }
        }

        //if (CastSpell(33395, pTarget)) // pet freeze spell
        //    sLog.outError ("successfully casted freeze");

        //AOE
        if (isUnderAttack(m_tank,5))
        {
            if (CastSpell(BLIZZARD,pTarget)) { return; }
        }

        //DPS
        if (m_bot->HasAura(P_FINGERS_OF_FROST) && CastSpell(DEEP_FREEZE,pTarget)) { return; }
        if (m_bot->HasAura(P_BRAIN_FREEZE) && CastSpell(FROSTFIRE_BOLT,pTarget)) { return; }
        if (CastSpell(FROSTBOLT,pTarget,true,true)) { return; }

    }

    // Defaults especialy for lower levels
    if (m_bot->HasAura(P_BRAIN_FREEZE) && CastSpell(FIREBALL,pTarget,1,1)) { return; }
        if (m_bot->HasAura(P_FIRESTARTER) && CastSpell(FLAMESTRIKE,pTarget,1,1)) { return; }
        if (m_bot->HasAura(P_HOT_STREAK) && CastSpell(PYROBLAST,pTarget,1,1)) { return; }
        if (m_bot->HasAura(POM) && (CastSpell(PYROBLAST,pTarget,1,1) || CastSpell(FIREBALL,pTarget,1,1) || CastSpell(FROSTBOLT,pTarget,1,1))) { return; }
        if (pTarget->isFrozen() && CastSpell(ICE_LANCE,pTarget)) { return; }
        if (m_bot->isMoving() && (CastSpell(FIRE_BLAST,pTarget,1,1) || CastSpell(ARCANE_BARRAGE,pTarget) || CastSpell(ICE_LANCE,pTarget))) { return; }
        if (CastSpell(FIREBALL,pTarget)) { return; }
        if (CastSpell(FROSTBOLT,pTarget)) { return; }
        if (CastSpell(ARCANE_MISSILES,pTarget)) { return; }

    // drink potion
    if(ai->GetManaPercent() < 5 )
    {
        Item *pItem = ai->FindPotion();
        if(pItem != NULL)
        {
            if (pItem->GetSpell() && m_bot->HasSpellCooldown(pItem->GetSpell()) ) { return; } //pot is in cooldown
            ai->UseItem(*pItem);
        }
    }

    // if we get down here, it means we are out of mana, so use wand
    CastSpell(SHOOT, pTarget);

} //end DoNextCombatManeuver
        void UpdateAI(const uint32 diff)
        {
            //Inhibitmagic_Timer
            if (Inhibitmagic_Timer <= diff)
            {
                float dist;
                Map* map = me->GetMap();
                Map::PlayerList const &PlayerList = map->GetPlayers();
                for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
                    if (Player* i_pl = i->getSource())
                        if (i_pl->isAlive() && (dist = i_pl->IsWithinDist(me, 45)))
                        {
                            i_pl->RemoveAurasDueToSpell(SPELL_INHIBITMAGIC);
                            me->AddAura(SPELL_INHIBITMAGIC, i_pl);
                            if (dist < 35)
                                me->AddAura(SPELL_INHIBITMAGIC, i_pl);
                            if (dist < 25)
                                me->AddAura(SPELL_INHIBITMAGIC, i_pl);
                            if (dist < 15)
                                me->AddAura(SPELL_INHIBITMAGIC, i_pl);
                        }
                Inhibitmagic_Timer = 3000+(rand()%1000);
            } else Inhibitmagic_Timer -= diff;

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

            //Attractmagic_Timer
            if (Attractmagic_Timer <= diff)
            {
                DoCast(me, SPELL_ATTRACTMAGIC);
                Attractmagic_Timer = 30000;
                Carnivorousbite_Timer = 1500;
            } else Attractmagic_Timer -= diff;

            //Carnivorousbite_Timer
            if (Carnivorousbite_Timer <= diff)
            {
                DoCast(me, SPELL_CARNIVOROUSBITE);
                Carnivorousbite_Timer = 10000;
            } else Carnivorousbite_Timer -= diff;

            //FocusFire_Timer
            if (FocusFire_Timer <= diff)
            {
                // Summon Focus Fire & Emote
                Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1);
                if (target && target->GetTypeId() == TYPEID_PLAYER && target->isAlive())
                {
                    FocusedTargetGUID = target->GetGUID();
                    me->SummonCreature(ENTRY_FOCUS_FIRE, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 5500);

                    // TODO: Find better way to handle emote
                    // Emote
                    std::string emote(EMOTE_FOCUSES_ON);
                    emote.append(target->GetName());
                    emote.push_back('!');
                    me->MonsterTextEmote(emote.c_str(), 0, true);
                }
                FocusFire_Timer = 15000+(rand()%5000);
            } else FocusFire_Timer -= diff;

            DoMeleeAttackIfReady();
        }
void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
{
    uint16 opcode = recvData.GetOpcode();

    Unit* mover = _player->m_mover;

    ASSERT(mover != NULL);                      // there must always be a mover

    Player* plrMover = mover->ToPlayer();

    // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
    if (plrMover && plrMover->IsBeingTeleported())
    {
        recvData.rfinish();                     // prevent warnings spam
        return;
    }

    /* extract packet */
    uint64 guid;

    recvData.readPackGUID(guid);

    MovementInfo movementInfo;
    movementInfo.guid = guid;
    ReadMovementInfo(recvData, &movementInfo);

    recvData.rfinish();                         // prevent warnings spam

    // prevent tampered movement data
    if (guid != mover->GetGUID())
        return;

    if (!movementInfo.pos.IsPositionValid())
    {
        recvData.rfinish();                     // prevent warnings spam
        return;
    }

    /* handle special cases */
    if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT)
    {
        // transports size limited
        // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
        if (movementInfo.t_pos.GetPositionX() > 50 || movementInfo.t_pos.GetPositionY() > 50 || movementInfo.t_pos.GetPositionZ() > 50)
        {
            recvData.rfinish();                 // prevent warnings spam
            return;
        }

        if (!Trinity::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.t_pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.t_pos.GetPositionY(),
            movementInfo.pos.GetPositionZ() + movementInfo.t_pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.t_pos.GetOrientation()))
        {
            recvData.rfinish();                 // prevent warnings spam
            return;
        }

        // if we boarded a transport, add us to it
        if (plrMover)
        {
            if (!plrMover->GetTransport())
            {
                // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just dismount if the guid can be found in the transport list
                for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter)
                {
                    if ((*iter)->GetGUID() == movementInfo.t_guid)
                    {
                        plrMover->m_transport = *iter;
                        (*iter)->AddPassenger(plrMover);
                        break;
                    }
                }
            }
            else if (plrMover->GetTransport()->GetGUID() != movementInfo.t_guid)
            {
                bool foundNewTransport = false;
                plrMover->m_transport->RemovePassenger(plrMover);
                for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter)
                {
                    if ((*iter)->GetGUID() == movementInfo.t_guid)
                    {
                        foundNewTransport = true;
                        plrMover->m_transport = *iter;
                        (*iter)->AddPassenger(plrMover);
                        break;
                    }
                }

                if (!foundNewTransport)
                {
                    plrMover->m_transport = NULL;
                    movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
                    movementInfo.t_time = 0;
                    movementInfo.t_seat = -1;
                }
            }
        }

        if (!mover->GetTransport() && !mover->GetVehicle())
        {
            GameObject* go = mover->GetMap()->GetGameObject(movementInfo.t_guid);
            if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT)
                movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT;
        }
    }
    else if (plrMover && plrMover->GetTransport())                // if we were on a transport, leave
    {
        plrMover->m_transport->RemovePassenger(plrMover);
        plrMover->m_transport = NULL;
        movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
        movementInfo.t_time = 0;
        movementInfo.t_seat = -1;
    }

    // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
    if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->isInFlight())
        plrMover->HandleFall(movementInfo);

    if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater())
    {
        // now client not include swimming flag in case jumping under water
        plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ()));
    }

    /*----------------------*/

    /* process position-change */
    WorldPacket data(opcode, recvData.size());
    movementInfo.time = getMSTime();
    movementInfo.guid = mover->GetGUID();
    WriteMovementInfo(&data, &movementInfo);
    mover->SendMessageToSet(&data, _player);

    mover->m_movementInfo = movementInfo;

    // this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle()
    if (mover->GetVehicle())
    {
        mover->SetOrientation(movementInfo.pos.GetOrientation());
        return;
    }

    mover->UpdatePosition(movementInfo.pos);

    if (plrMover)                                            // nothing is charmed, or player charmed
    {
        plrMover->UpdateFallInformationIfNeed(movementInfo, opcode);

        float underMapValueZ;	
       switch (plrMover->GetMapId())	
        {
            case 617: underMapValueZ = 3.0f; break; // Dalaran Sewers
            case 618: underMapValueZ = 28.0f; break; // Ring of Valor
            case 562: underMapValueZ = -10.0f; break; // Blade Edge Arena
            case 559: underMapValueZ = -18.0f; break; // Nagrand arena
            case 572: underMapValueZ = 28.0f; break; // Lordearon
            case 571: underMapValueZ = -400.0f; break; // Northrend

            default: underMapValueZ = -500.0f; break;
        }

        if (movementInfo.pos.GetPositionZ() < underMapValueZ)
        {
            if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player)))
            {
                // NOTE: this is actually called many times while falling
                // even after the player has been teleported away
                /// @todo discard movement packets after the player is rooted
                if (plrMover->isAlive())
                {
                    plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
                    // player can be alive if GM/etc
                    // change the death state to CORPSE to prevent the death timer from
                    // starting in the next player update
                    if (!plrMover->isAlive())
                        plrMover->KillPlayer();
                }
            }
        }
    }
}
            void UpdateAI(const uint32 diff)
            {
                if (!UpdateVictim())
                    return;

                if (ResetTimer <= diff)
                {
                    if (me->IsWithinDist3d(119.223f, 1035.45f, 29.4481f, 10))
                    {
                        EnterEvadeMode();
                        return;
                    }
                    ResetTimer = 5000;
                } else ResetTimer -= diff;

                if (CheckAddState_Timer <= diff)
                {
                    for (uint8 i = 0; i < 4; ++i)
                        if (Creature* temp = Unit::GetCreature(*me, AddGUID[i]))
                            if (temp->isAlive() && !temp->getVictim())
                                temp->AI()->AttackStart(me->getVictim());

                    CheckAddState_Timer = 5000;
                } else CheckAddState_Timer -= diff;

                if (DrainPower_Timer <= diff)
                {
                    DoCast(me, SPELL_DRAIN_POWER, true);
                    me->MonsterYell(YELL_DRAIN_POWER, LANG_UNIVERSAL, 0);
                    DoPlaySoundToSet(me, SOUND_YELL_DRAIN_POWER);
                    DrainPower_Timer = urand(40000, 55000);    // must cast in 60 sec, or buff/debuff will disappear
                } else DrainPower_Timer -= diff;

                if (SpiritBolts_Timer <= diff)
                {
                    if (DrainPower_Timer < 12000)    // channel 10 sec
                        SpiritBolts_Timer = 13000;   // cast drain power first
                    else
                    {
                        DoCast(me, SPELL_SPIRIT_BOLTS, false);
                        me->MonsterYell(YELL_SPIRIT_BOLTS, LANG_UNIVERSAL, 0);
                        DoPlaySoundToSet(me, SOUND_YELL_SPIRIT_BOLTS);
                        SpiritBolts_Timer   = 40000;
                        SiphonSoul_Timer    = 10000;    // ready to drain
                        PlayerAbility_Timer = 99999;
                    }
                } else SpiritBolts_Timer -= diff;

                if (SiphonSoul_Timer <= diff)
                {
                    Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 70, true);
                    Unit* trigger = DoSpawnCreature(MOB_TEMP_TRIGGER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 30000);
                    if (!target || !trigger)
                    {
                        EnterEvadeMode();
                        return;
                    }
                    else
                    {
                        trigger->SetDisplayId(11686);
                        trigger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
                        trigger->CastSpell(target, SPELL_SIPHON_SOUL, true);
                        trigger->GetMotionMaster()->MoveChase(me);

                        //DoCast(target, SPELL_SIPHON_SOUL, true);
                        //me->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, target->GetGUID());
                        //me->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_SIPHON_SOUL);

                        PlayerGUID = target->GetGUID();
                        PlayerAbility_Timer = urand(8000, 10000);
                        PlayerClass = target->getClass() - 1;

                        if (PlayerClass == CLASS_DRUID-1)
                            PlayerClass = CLASS_DRUID;
                        else if (PlayerClass == CLASS_PRIEST-1 && target->HasSpell(15473))
                            PlayerClass = CLASS_PRIEST; // shadow priest

                        SiphonSoul_Timer = 99999;   // buff lasts 30 sec
                    }
                } else SiphonSoul_Timer -= diff;

                if (PlayerAbility_Timer <= diff)
                {
                    //Unit* target = Unit::GetUnit(*me, PlayerGUID);
                    //if (target && target->isAlive())
                    //{
                        UseAbility();
                        PlayerAbility_Timer = urand(8000, 10000);
                    //}
                } else PlayerAbility_Timer -= diff;

                DoMeleeAttackIfReady();
            }
        void UpdateAI(const uint32 diff)
        {
            if (!UpdateVictim())
                return;

            if (ArcingSmashTimer <= diff)
            {
                DoCast(me->getVictim(), SPELL_ARCING_SMASH);
                ArcingSmashTimer = 10000;
            } else ArcingSmashTimer -= diff;

            if (FelAcidTimer <= diff)
            {
                DoCast(me->getVictim(), SPELL_FEL_ACID);
                FelAcidTimer = 25000;
            } else FelAcidTimer -= diff;

            if (!me->HasAura(SPELL_BERSERK))
            {
                if (EnrageTimer <= diff)
                {
                    DoCast(me, SPELL_BERSERK);
                    DoScriptText(RAND(SAY_ENRAGE1, SAY_ENRAGE2), me);
                } else EnrageTimer -= diff;
            }

            if (Phase1)
            {
                if (BewilderingStrikeTimer <= diff)
                {
                    DoCast(me->getVictim(), SPELL_BEWILDERING_STRIKE);
                    float mt_threat = DoGetThreat(me->getVictim());
                    if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1))
                        me->AddThreat(target, mt_threat);
                    BewilderingStrikeTimer = 20000;
                } else BewilderingStrikeTimer -= diff;

                if (EjectTimer <= diff)
                {
                    DoCast(me->getVictim(), SPELL_EJECT1);
                    DoModifyThreatPercent(me->getVictim(), -40);
                    EjectTimer = 15000;
                } else EjectTimer -= diff;

                if (AcidicWoundTimer <= diff)
                {
                    DoCast(me->getVictim(), SPELL_ACIDIC_WOUND);
                    AcidicWoundTimer = 10000;
                } else AcidicWoundTimer -= diff;

                if (BloodboilTimer <= diff)
                {
                    if (BloodboilCount < 5)                      // Only cast it five times.
                    {
                        //CastBloodboil(); // Causes issues on windows, so is commented out.
                        DoCast(me->getVictim(), SPELL_BLOODBOIL);
                        ++BloodboilCount;
                        BloodboilTimer = 10000*BloodboilCount;
                    }
                } else BloodboilTimer -= diff;
            }

            if (!Phase1)
            {
                if (AcidGeyserTimer <= diff)
                {
                    DoCast(me->getVictim(), SPELL_ACID_GEYSER);
                    AcidGeyserTimer = 30000;
                } else AcidGeyserTimer -= diff;

                if (EjectTimer <= diff)
                {
                    DoCast(me->getVictim(), SPELL_EJECT2);
                    EjectTimer = 15000;
                } else EjectTimer -= diff;
            }

            if (PhaseChangeTimer <= diff)
            {
                if (Phase1)
                {
                    Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0);
                    if (target && target->isAlive())
                    {
                        Phase1 = false;

                        TargetThreat = DoGetThreat(target);
                        TargetGUID = target->GetGUID();
                        target->CastSpell(me, SPELL_TAUNT_GURTOGG, true);
                        if (DoGetThreat(target))
                            DoModifyThreatPercent(target, -100);
                        me->AddThreat(target, 50000000.0f);
                        me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
                        me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true);
                                                                // If VMaps are disabled, this spell can call the whole instance
                        DoCast(me, SPELL_INSIGNIFIGANCE, true);
                        DoCast(target, SPELL_FEL_RAGE_TARGET, true);
                        DoCast(target, SPELL_FEL_RAGE_2, true);
                        /* These spells do not work, comment them out for now.
                        DoCast(target, SPELL_FEL_RAGE_2, true);
                        DoCast(target, SPELL_FEL_RAGE_3, true);*/

                        //Cast this without triggered so that it appears in combat logs and shows visual.
                        DoCast(me, SPELL_FEL_RAGE_SELF);

                        DoScriptText(RAND(SAY_SPECIAL1, SAY_SPECIAL2), me);

                        AcidGeyserTimer = 1000;
                        PhaseChangeTimer = 30000;
                    }
                } else                                           // Encounter is a loop pretty much. Phase 1 -> Phase 2 -> Phase 1 -> Phase 2 till death or enrage
                {
                    if (TargetGUID)
                        RevertThreatOnTarget(TargetGUID);
                    TargetGUID = 0;
                    Phase1 = true;
                    BloodboilTimer = 10000;
                    BloodboilCount = 0;
                    AcidicWoundTimer += 2000;
                    ArcingSmashTimer += 2000;
                    FelAcidTimer += 2000;
                    EjectTimer += 2000;
                    PhaseChangeTimer = 60000;
                    me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
                    me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false);
                }
            } else PhaseChangeTimer -= diff;

            DoMeleeAttackIfReady();
        }
Beispiel #8
0
    void UpdateAI(const uint32 diff)
    {
        if (!UpdateVictim())
            return;

        if (Summon_Timer <= diff)
        {
            me->InterruptNonMeleeSpells(false);
            DoCast(me, SPELL_SUMMON_FIENDISH_HOUND);
            Summon_Timer = 24100+rand()%2800;
        } else Summon_Timer -= diff;

        if (CanPullBack)
        {
            if (ShadowWhip_Timer <= diff)
            {
                if (Unit* temp = Unit::GetUnit(*me, playerGUID))
                {
                    //if unit dosen't have this flag, then no pulling back (script will attempt cast, even if orbital strike was resisted)
                    if (temp->HasUnitMovementFlag(MOVEFLAG_FALLING))
                    {
                        me->InterruptNonMeleeSpells(false);
                        DoCast(temp, SPELL_SHADOW_WHIP);
                    }
                    else
                        if (!temp->HasUnitMovementFlag(MOVEFLAG_FALLING))
                        {
                            playerGUID = 0;
                            CanPullBack = false;
                        }
                }
                ShadowWhip_Timer = 2000;
            } else ShadowWhip_Timer -= diff;
        }
        else if (OrbitalStrike_Timer <= diff)
        {
            Unit* temp = NULL;
            if (me->IsWithinMeleeRange(me->getVictim()))
                temp = me->getVictim();
            else temp = SelectUnit(SELECT_TARGET_RANDOM, 0);

            if (temp && temp->GetTypeId() == TYPEID_PLAYER)
            {
                me->InterruptNonMeleeSpells(false);
                DoCast(temp, SPELL_ORBITAL_STRIKE);
                OrbitalStrike_Timer = 14000+rand()%2000;
                playerGUID = temp->GetGUID();

                if (playerGUID)
                {
                    CanPullBack = true;
                    ShadowWhip_Timer = 2500;
                }
            }
        } else OrbitalStrike_Timer -= diff;

        if ((me->GetHealth()*100) / me->GetMaxHealth() < 20)
        {
            if (DemonicShield_Timer <= diff)
            {
                DoCast(me, SPELL_DEMONIC_SHIELD);
                DemonicShield_Timer = 15000;
            } else DemonicShield_Timer -= diff;
        }

        if (Aura_Timer <= diff)
        {
            DoScriptText(SAY_CURSE, me);

            if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
            {
                DoCast(pTarget, HeroicMode ? H_SPELL_BANE_OF_TREACHERY : SPELL_TREACHEROUS_AURA);
                Aura_Timer = 8000+rand()%8000;
            }
        } else Aura_Timer -= diff;

        if (Shadowbolt_Timer <= diff)
        {
            if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
            {
                if (pTarget)
                    pTarget = me->getVictim();

                DoCast(pTarget, HeroicMode ? H_SPELL_SHADOW_BOLT : SPELL_SHADOW_BOLT);
                Shadowbolt_Timer = 4000+rand()%3100;
            }
        } else Shadowbolt_Timer -= diff;

        DoMeleeAttackIfReady();
    }
Beispiel #9
0
        void UpdateAI(const uint32 diff)
        {
            if(!UpdateVictim())
                return;
        
            if(Phase1)
            {
                if(pulse_Timer < diff)
                {
                    if(me->GetPositionZ() > (COORD_Z_HOME+15))
                    {
                        EnterEvadeMode();
                        return;
                    }

                    DoAttackerAreaInCombat(me->getVictim(),50);
                    pulse_Timer = 10000;
                }else pulse_Timer -= diff;
            }

            if(!me->HasAura(SPELL_BERSERK, 0))
            {
                if(EnrageTimer < diff)
                {
                    DoCast(me, SPELL_BERSERK);
                    switch(rand()%2)
                    {
                    case 0: DoScriptText(SAY_ENRAGE1, me); break;
                    case 1: DoScriptText(SAY_ENRAGE2, me); break;
                    }
                }else EnrageTimer -= diff;
            }

            if(ArcingSmashTimer < diff)
            {
                DoCast(me->getVictim(),Phase1 ? SPELL_ARCING_SMASH_1 : SPELL_ARCING_SMASH_2);
                ArcingSmashTimer = 10000;
            }else ArcingSmashTimer -= diff;

            if(FelBreathTimer < diff)
            {
                DoCast(me->getVictim(),Phase1 ? SPELL_FELBREATH_1 : SPELL_FELBREATH_2);
                FelBreathTimer = 25000;
            }else FelBreathTimer -= diff;

            if(EjectTimer < diff)
            {
                DoCast(me->getVictim(),Phase1 ? SPELL_EJECT_1 : SPELL_EJECT_2);
                EjectTimer = 15000;
            }else EjectTimer -= diff;


            if(Charge_Timer < diff)
            {
                if(me->GetDistance2d(me->getVictim()) > 15)
                    DoCast(me->getVictim(),SPELL_CHARGE);
                Charge_Timer = 10000;
            }else Charge_Timer -= diff;

            if(Phase1)
            {
                if(BewilderingStrikeTimer < diff)
                {
                    DoCast(me->getVictim(), SPELL_BEWILDERING_STRIKE);
                    //float mt_threat = DoGetThreat(me->getVictim());
                    //if (Unit* target = SelectUnit(SELECT_TARGET_TOPAGGRO, 1))
                    //    me->AddThreat(target, mt_threat);
                    BewilderingStrikeTimer = 20000;
                }else BewilderingStrikeTimer -= diff;

                //if(EjectTimer < diff)
                //{
                //    DoCast(me->getVictim(), SPELL_EJECT1);
                //    DoModifyThreatPercent(me->getVictim(), -40);
                //    EjectTimer = 15000;
                //}else EjectTimer -= diff;

                //if(AcidicWoundTimer < diff)
                //{
                //    DoCast(me->getVictim(), SPELL_ACIDIC_WOUND);
                //    AcidicWoundTimer = 10000;
                //}else AcidicWoundTimer -= diff;

                if(BloodboilTimer < diff)
                {
                    if(BloodboilCount < 5)                      // Only cast it five times.
                    {
                        CastBloodboil(); // Causes issues on windows, so is commented out.
                        //DoCast(me->getVictim(), SPELL_BLOODBOIL);
                        ++BloodboilCount;
                        BloodboilTimer = 10000;
                    }
                }else BloodboilTimer -= diff;
            }

            if(!Phase1)
            {
                //if(FelGeyserTimer < diff)
                //{
                //    DoCast(me->getVictim(), SPELL_FEL_GEYSER,true);
                //    FelGeyserTimer = 30000;
                //}else FelGeyserTimer -= diff;

                if(me->getVictim() && me->getVictim()->IsImmunedToDamage(SPELL_SCHOOL_MASK_ALL))
                    me->getThreatManager().modifyThreatPercent(me->getVictim(),-100);
            }

            if(PhaseChangeTimer < diff)
            {
                if(Phase1)
                {
                    Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0,100,true);
                    if(target && target->isAlive())
                    {
                        Phase1 = false;

                        TargetThreat = DoGetThreat(target);
                        TargetGUID = target->GetGUID();
                        if(DoGetThreat(target))
                            DoModifyThreatPercent(target, -100);
                        me->AddThreat(target, 50000000.0f);
                        target->CastSpell(me, SPELL_TAUNT_GURTOGG, true);
                        me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
                        me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true);

                        // If VMaps are disabled, this spell can call the whole instance
                        DoCast(me, SPELL_INSIGNIFIGANCE, true);
                        DoCast(target,SPELL_FEL_RAGE_1, true);
                        DoCast(target,SPELL_FEL_RAGE_2, true);
                        DoCast(target,SPELL_FEL_RAGE_3, true);
                        DoCast(target,SPELL_FEL_RAGE_SCALE, true);
                        DoCast(target,SPELL_FEL_GEYSER,true);

                        //Cast this without triggered so that it appears in combat logs and shows visual.
                        DoCast(me, SPELL_FEL_RAGE_SELF);

                        switch(rand()%2)
                        {
                        case 0: DoScriptText(SAY_SPECIAL1, me); break;
                        case 1: DoScriptText(SAY_SPECIAL2, me); break;
                        }

                        FelGeyserTimer = 1;
                        PhaseChangeTimer = 30000;
                    }
                }else                                           // Encounter is a loop pretty much. Phase 1 -> Phase 2 -> Phase 1 -> Phase 2 till death or enrage
                {
                    if(TargetGUID)
                        RevertThreatOnTarget(TargetGUID);
                    TargetGUID = 0;
                    Phase1 = true;
                    BloodboilTimer = 10000;
                    BloodboilCount = 0;
                    /*AcidicWoundTimer += 2000;*/
                    ArcingSmashTimer += 2000;
                    FelBreathTimer += 2000;
                    EjectTimer += 2000;
                    PhaseChangeTimer = 65000;
                    me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
                    me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false);
                }
            }else PhaseChangeTimer -= diff;

            DoMeleeAttackIfReady();
        }
Beispiel #10
0
            void HandleDummy(SpellEffIndex /* effIndex */)
            {
                int32 damage = GetEffectValue();
                Unit* caster = GetCaster();
                if (Unit* target = GetHitUnit())
                {
                    // apply percent damage mods
                    damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE);

                    ApplyPctN(damage, 16 * sSpellMgr->GetSpellRank(GetSpellInfo()->Id));

                    damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE);

                    SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_DEEP_WOUNDS_RANK_PERIODIC);
                    uint32 ticks = spellInfo->GetDuration() / spellInfo->Effects[EFFECT_0].Amplitude;

                    // Add remaining ticks to damage done
                    if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_DEEP_WOUNDS_RANK_PERIODIC, EFFECT_0, caster->GetGUID()))
                        damage += aurEff->GetAmount() * (ticks - aurEff->GetTickNumber());

                    damage = damage / ticks;

                    caster->CastCustomSpell(target, SPELL_DEEP_WOUNDS_RANK_PERIODIC, &damage, NULL, NULL, true);
                }
            }
            void UpdateAI(uint32 diff) override
            {
                if (!UpdateVictim())
                    return;

                //only two may be wrong, perhaps increase timer and spawn periodically instead.
                if (SummonedCount < 2)
                {
                    if (Summon_Timer <= diff)
                    {
                        me->InterruptNonMeleeSpells(false);
                        DoCast(me, SPELL_SUMMON_FIENDISH_HOUND);
                        Summon_Timer = 15000 + rand32() % 15000;
                    }
                    else
                        Summon_Timer -= diff;
                }

                if (CanPullBack)
                {
                    if (ShadowWhip_Timer <= diff)
                    {
                        if (Player* temp = ObjectAccessor::GetPlayer(*me, PlayerGUID))
                        {
                            //if unit dosen't have this flag, then no pulling back (script will attempt cast, even if orbital strike was resisted)
                            if (temp->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR))
                            {
                                me->InterruptNonMeleeSpells(false);
                                DoCast(temp, SPELL_SHADOW_WHIP);
                            }
                        }
                        PlayerGUID = 0;
                        ShadowWhip_Timer = 2000;
                        CanPullBack = false;
                    }
                    else
                        ShadowWhip_Timer -= diff;
                }
                else
                    if (OrbitalStrike_Timer <= diff)
                    {
                        Unit* temp = NULL;
                        if (me->IsWithinMeleeRange(me->GetVictim()))
                            temp = me->GetVictim();
                        else temp = SelectTarget(SELECT_TARGET_RANDOM, 0);

                        if (temp && temp->GetTypeId() == TYPEID_PLAYER)
                        {
                            DoCast(temp, SPELL_ORBITAL_STRIKE);
                            OrbitalStrike_Timer = 14000 + rand32() % 2000;
                            PlayerGUID = temp->GetGUID();

                            if (PlayerGUID)
                                CanPullBack = true;
                        }
                    }
                    else
                        OrbitalStrike_Timer -= diff;

                if (HealthBelowPct(20))
                {
                    if (DemonicShield_Timer <= diff)
                    {
                        DoCast(me, SPELL_DEMONIC_SHIELD);
                        DemonicShield_Timer = 15000;
                    }
                    else
                        DemonicShield_Timer -= diff;
                }

                if (Aura_Timer <= diff)
                {
                    Talk(SAY_CURSE);

                    if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
                    {
                        DoCast(target, SPELL_TREACHEROUS_AURA);
                        Aura_Timer = 8000 + rand32() % 8000;
                    }
                }
                else
                    Aura_Timer -= diff;

                if (Shadowbolt_Timer <= diff)
                {
                    if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
                    {
                        if (target)
                            target = me->GetVictim();

                        DoCast(target, SPELL_SHADOW_BOLT);
                        Shadowbolt_Timer = 4000 + rand32() % 2500;
                    }
                }
                else
                    Shadowbolt_Timer -= diff;

                DoMeleeAttackIfReady();
            }
Beispiel #12
0
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/
void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
{
    sLog.outDebug("WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS");
    uint64 Guid;
    recv_data >> Guid;

    Player *player = sObjectMgr.GetPlayer(Guid);
    if(!player)
    {
        WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2);
        data << uint8(0);                                   // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
        data.appendPackGUID(Guid);
        data << uint32(GROUP_UPDATE_FLAG_STATUS);
        data << uint16(MEMBER_STATUS_OFFLINE);
        SendPacket(&data);
        return;
    }

    Unit *pet = player->GetCharmOrPet();

    WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8);
    data << uint8(0);                                       // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
    data << player->GetPackGUID();

    uint32 mask1 = 0x00040BFF;                              // common mask, real flags used 0x000040BFF
    if(pet)
        mask1 = 0xFFFFFFFF;                                 // for hunters and other classes with pets

    Powers powerType = player->getPowerType();
    data << uint32(mask1);                                  // group update mask
    data << uint16(MEMBER_STATUS_ONLINE);                   // member's online status
    data << uint32(player->GetHealth());                    // GROUP_UPDATE_FLAG_CUR_HP
    data << uint32(player->GetMaxHealth());                 // GROUP_UPDATE_FLAG_MAX_HP
    data << uint8(powerType);                               // GROUP_UPDATE_FLAG_POWER_TYPE
    data << uint16(player->GetPower(powerType));            // GROUP_UPDATE_FLAG_CUR_POWER
    data << uint16(player->GetMaxPower(powerType));         // GROUP_UPDATE_FLAG_MAX_POWER
    data << uint16(player->getLevel());                     // GROUP_UPDATE_FLAG_LEVEL
    data << uint16(player->GetZoneId());                    // GROUP_UPDATE_FLAG_ZONE
    data << uint16(player->GetPositionX());                 // GROUP_UPDATE_FLAG_POSITION
    data << uint16(player->GetPositionY());                 // GROUP_UPDATE_FLAG_POSITION

    uint64 auramask = 0;
    size_t maskPos = data.wpos();
    data << uint64(auramask);                               // placeholder
    for(uint8 i = 0; i < MAX_AURAS; ++i)
    {
        if(uint32 aura = player->GetVisibleAura(i))
        {
            auramask |= (uint64(1) << i);
            data << uint32(aura);
            data << uint8(1);
        }
    }
    data.put<uint64>(maskPos, auramask);                    // GROUP_UPDATE_FLAG_AURAS

    if(pet)
    {
        Powers petpowertype = pet->getPowerType();
        data << uint64(pet->GetGUID());                     // GROUP_UPDATE_FLAG_PET_GUID
        data << pet->GetName();                             // GROUP_UPDATE_FLAG_PET_NAME
        data << uint16(pet->GetDisplayId());                // GROUP_UPDATE_FLAG_PET_MODEL_ID
        data << uint32(pet->GetHealth());                   // GROUP_UPDATE_FLAG_PET_CUR_HP
        data << uint32(pet->GetMaxHealth());                // GROUP_UPDATE_FLAG_PET_MAX_HP
        data << uint8(petpowertype);                        // GROUP_UPDATE_FLAG_PET_POWER_TYPE
        data << uint16(pet->GetPower(petpowertype));        // GROUP_UPDATE_FLAG_PET_CUR_POWER
        data << uint16(pet->GetMaxPower(petpowertype));     // GROUP_UPDATE_FLAG_PET_MAX_POWER

        uint64 petauramask = 0;
        size_t petMaskPos = data.wpos();
        data << uint64(petauramask);                        // placeholder
        for(uint8 i = 0; i < MAX_AURAS; ++i)
        {
            if(uint32 petaura = pet->GetVisibleAura(i))
            {
                petauramask |= (uint64(1) << i);
                data << uint32(petaura);
                data << uint8(1);
            }
        }

        data.put<uint64>(petMaskPos,petauramask);           // GROUP_UPDATE_FLAG_PET_AURAS
        data << (uint32) player->m_SeatData.dbc_seat;
    }
    else
    {
        data << uint8(0);                                   // GROUP_UPDATE_FLAG_PET_NAME
        data << uint64(0);                                  // GROUP_UPDATE_FLAG_PET_AURAS
    }

    SendPacket(&data);
}
Beispiel #13
0
void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacket *data)
{
    uint32 mask = player->GetGroupUpdateFlag();

    if (mask == GROUP_UPDATE_FLAG_NONE)
        return;

    if (mask & GROUP_UPDATE_FLAG_POWER_TYPE)                // if update power type, update current/max power also
        mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER);

    if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE)            // same for pets
        mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER);

    uint32 byteCount = 0;
    for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i)
        if (mask & (1 << i))
            byteCount += GroupUpdateLength[i];

    data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount);
    *data << player->GetPackGUID();
    *data << uint32(mask);

    if (mask & GROUP_UPDATE_FLAG_STATUS)
    {
        if (player)
        {
            if (player->IsPvP())
                *data << uint16(MEMBER_STATUS_ONLINE | MEMBER_STATUS_PVP);
            else
                *data << uint16(MEMBER_STATUS_ONLINE);
        }
        else
            *data << uint16(MEMBER_STATUS_OFFLINE);
    }

    if (mask & GROUP_UPDATE_FLAG_CUR_HP)
        *data << uint32(player->GetHealth());

    if (mask & GROUP_UPDATE_FLAG_MAX_HP)
        *data << uint32(player->GetMaxHealth());

    Powers powerType = player->getPowerType();
    if (mask & GROUP_UPDATE_FLAG_POWER_TYPE)
        *data << uint8(powerType);

    if (mask & GROUP_UPDATE_FLAG_CUR_POWER)
        *data << uint16(player->GetPower(powerType));

    if (mask & GROUP_UPDATE_FLAG_MAX_POWER)
        *data << uint16(player->GetMaxPower(powerType));

    if (mask & GROUP_UPDATE_FLAG_LEVEL)
        *data << uint16(player->getLevel());

    if (mask & GROUP_UPDATE_FLAG_ZONE)
        *data << uint16(player->GetZoneId());

    if (mask & GROUP_UPDATE_FLAG_POSITION)
        *data << uint16(player->GetPositionX()) << uint16(player->GetPositionY());

    if (mask & GROUP_UPDATE_FLAG_AURAS)
    {
        const uint64& auramask = player->GetAuraUpdateMask();
        *data << uint64(auramask);
        for(uint32 i = 0; i < MAX_AURAS; ++i)
        {
            if(auramask & (uint64(1) << i))
            {
                *data << uint32(player->GetVisibleAura(i));
                *data << uint8(1);
            }
        }
    }

    Unit *pet = player->GetCharmOrPet();
    if (mask & GROUP_UPDATE_FLAG_PET_GUID)
    {
        if(pet)
            *data << uint64(pet->GetGUID());
        else
            *data << uint64(0);
    }

    if (mask & GROUP_UPDATE_FLAG_PET_NAME)
    {
        if(pet)
            *data << pet->GetName();
        else
            *data << uint8(0);
    }

    if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID)
    {
        if(pet)
            *data << uint16(pet->GetDisplayId());
        else
            *data << uint16(0);
    }

    if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP)
    {
        if(pet)
            *data << uint32(pet->GetHealth());
        else
            *data << uint32(0);
    }

    if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP)
    {
        if(pet)
            *data << uint32(pet->GetMaxHealth());
        else
            *data << uint32(0);
    }

    if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE)
    {
        if(pet)
            *data << uint8(pet->getPowerType());
        else
            *data << uint8(0);
    }

    if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER)
    {
        if(pet)
            *data << uint16(pet->GetPower(pet->getPowerType()));
        else
            *data << uint16(0);
    }

    if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER)
    {
        if(pet)
            *data << uint16(pet->GetMaxPower(pet->getPowerType()));
        else
            *data << uint16(0);
    }

    if (mask & GROUP_UPDATE_FLAG_PET_AURAS)
    {
        if(pet)
        {
            const uint64& auramask = pet->GetAuraUpdateMask();
            *data << uint64(auramask);
            for(uint32 i = 0; i < MAX_AURAS; ++i)
            {
                if(auramask & (uint64(1) << i))
                {
                    *data << uint32(pet->GetVisibleAura(i));
                    *data << uint8(1);
                }
            }
        }
        else
            *data << uint64(0);
    }

    if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
    {
        *data << (uint32) player->m_SeatData.dbc_seat;
    }
}
        void UpdateAI(uint32 diff) override
        {
            if (TalkTimer)
            {
                if (!TalkSequence)
                {
                    me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE);
                    me->InterruptNonMeleeSpells(true);
                    me->RemoveAllAuras();
                    me->DeleteThreatList();
                    me->CombatStop();
                    ++TalkSequence;
                }
                if (TalkTimer <= diff)
                {
                    if (isFriendly)
                        GoodEnding();
                    else
                        BadEnding();
                    ++TalkSequence;
                } else TalkTimer -= diff;
            }
            else
            {
                if (bJustReset)
                {
                    if (ResetTimer <= diff)
                    {
                        me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
                        me->SetDisableGravity(false);
                        me->SetVisible(true);
                        me->SetStandState(UNIT_STAND_STATE_SLEEP);
                        ResetTimer = 10000;
                        bJustReset = false;
                    } else ResetTimer -= diff;
                    return;
                }

                if (!UpdateVictim())
                    return;

                if (CheckTimer <= diff)
                {
                    if (me->GetDistance(CENTER_X, CENTER_Y, DRAGON_REALM_Z) >= 75)
                    {
                        EnterEvadeMode();
                        return;
                    }
                    if (HealthBelowPct(10) && !isEnraged)
                    {
                        if (Creature* Sath = ObjectAccessor::GetCreature(*me, SathGUID))
                            Sath->AI()->DoAction(DO_ENRAGE);
                        DoAction(DO_ENRAGE);
                    }
                    if (!isBanished && HealthBelowPct(1))
                    {
                        if (Creature* Sath = ObjectAccessor::GetCreature(*me, SathGUID))
                        {
                            if (Sath->HasAura(SPELL_BANISH))
                            {
                                Sath->DealDamage(Sath, Sath->GetHealth());
                                return;
                            }
                            else
                                DoAction(DO_BANISH);
                        }
                        else
                        {
                            TC_LOG_ERROR("scripts", "Didn't find Shathrowar. Kalecgos event reseted.");
                            EnterEvadeMode();
                            return;
                        }
                    }
                    CheckTimer = 1000;
                } else CheckTimer -= diff;

                if (ArcaneBuffetTimer <= diff)
                {
                    DoCastAOE(SPELL_ARCANE_BUFFET);
                    ArcaneBuffetTimer = 8000;
                } else ArcaneBuffetTimer -= diff;

                if (FrostBreathTimer <= diff)
                {
                    DoCastAOE(SPELL_FROST_BREATH);
                    FrostBreathTimer = 15000;
                } else FrostBreathTimer -= diff;

                if (TailLashTimer <= diff)
                {
                    DoCastAOE(SPELL_TAIL_LASH);
                    TailLashTimer = 15000;
                } else TailLashTimer -= diff;

                if (WildMagicTimer <= diff)
                {
                    DoCastAOE(WildMagic[rand()%6]);
                    WildMagicTimer = 20000;
                } else WildMagicTimer -= diff;

                if (SpectralBlastTimer <= diff)
                {
                    ThreatContainer::StorageType const& m_threatlist = me->getThreatManager().getThreatList();
                    std::list<Unit*> targetList;
                    for (ThreatContainer::StorageType::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr)
                    {
                        Unit* target = (*itr)->getTarget();
                        if (target
                                && target->GetTypeId() == TYPEID_PLAYER
                                && (!target->GetVictim() || target->GetGUID() != me->EnsureVictim()->GetGUID())
                                && target->GetPositionZ() > me->GetPositionZ() - 5
                                && !target->HasAura(AURA_SPECTRAL_EXHAUSTION))
                        {
                            targetList.push_back(target);
                        }
                    }
                    if (targetList.empty())
                    {
                        SpectralBlastTimer = 1000;
                        return;
                    }

                    std::list<Unit*>::const_iterator i = targetList.begin();
                    advance(i, rand()%targetList.size());
                    if ((*i))
                    {
                        (*i)->CastSpell((*i), SPELL_SPECTRAL_BLAST, true);
                        SpectralBlastTimer = 20000+rand()%5000;
                    } else SpectralBlastTimer = 1000;
                } else SpectralBlastTimer -= diff;

                DoMeleeAttackIfReady();
            }
        }
Beispiel #15
0
    void UpdateAI(const uint32 diff)
    {
        //Check if we have a target
        if (!m_creature->SelectHostilTarget() || !m_creature->getVictim())
            return;

        //No instance
        if (!pInstance)
            return;

        switch (pInstance->GetData(DATA_CTHUN_PHASE))
        {
            case 0:
            {
                //BeamTimer
                if (BeamTimer < diff)
                {
                    //SPELL_GREEN_BEAM
                    Unit* target = NULL;
                    target = SelectUnit(SELECT_TARGET_RANDOM,0);
                    if (target)
                    {
                        m_creature->InterruptNonMeleeSpells(false);
                        DoCast(target,SPELL_GREEN_BEAM);

                        //Correctly update our target
                        m_creature->SetUInt64Value(UNIT_FIELD_TARGET, target->GetGUID());
                    }

                    //Beam every 3 seconds
                    BeamTimer = 3000;
                }else BeamTimer -= diff;

                //ClawTentacleTimer
                if (ClawTentacleTimer < diff)
                {
                    Unit* target = NULL;
                    target = SelectUnit(SELECT_TARGET_RANDOM,0);
                    if (target)
                    {
                        Creature* Spawned = NULL;

                        //Spawn claw tentacle on the random target
                        Spawned = (Creature*)m_creature->SummonCreature(MOB_CLAW_TENTACLE,target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,500);

                        if (Spawned)
                            Spawned->AI()->AttackStart(target);
                    }

                    //One claw tentacle every 12.5 seconds
                    ClawTentacleTimer = 12500;
                }else ClawTentacleTimer -= diff;

                //EyeTentacleTimer
                if (EyeTentacleTimer < diff)
                {
                    //Spawn the 8 Eye Tentacles in the corret spots
                    SpawnEyeTentacle(0, 20);                //south
                    SpawnEyeTentacle(10, 10);               //south west
                    SpawnEyeTentacle(20, 0);                //west
                    SpawnEyeTentacle(10, -10);              //north west

                    SpawnEyeTentacle(0, -20);               //north
                    SpawnEyeTentacle(-10, -10);             //north east
                    SpawnEyeTentacle(-20, 0);               // east
                    SpawnEyeTentacle(-10, 10);              // south east

                    //No point actually putting a timer here since
                    //These shouldn't trigger agian until after phase shifts
                    EyeTentacleTimer = 45000;
                }else EyeTentacleTimer -= diff;

                //PhaseTimer
                if (PhaseTimer < diff)
                {
                    //Switch to Dark Beam
                    pInstance->SetData(DATA_CTHUN_PHASE, 1);

                    m_creature->InterruptNonMeleeSpells(false);

                    //Select random target for dark beam to start on
                    Unit* target = NULL;
                    target = SelectUnit(SELECT_TARGET_RANDOM,0);

                    if (target)
                    {
                        //Correctly update our target
                        m_creature->SetUInt64Value(UNIT_FIELD_TARGET, target->GetGUID());

                        //Face our target
                        DarkGlareAngle = m_creature->GetAngle(target);
                        DarkGlareTickTimer = 1000;
                        DarkGlareTick = 0;
                        ClockWise = rand()%2;
                    }

                    //Add red coloration to C'thun
                    DoCast(m_creature,SPELL_RED_COLORATION);

                    //Freeze animation

                    //Darkbeam for 35 seconds
                    PhaseTimer = 35000;
                }else PhaseTimer -= diff;

            }
            break;
            case 1:
            {
                //EyeTentacleTimer
                if (DarkGlareTick < 35)
                    if (DarkGlareTickTimer < diff)
                {
                    //Remove any target
                    m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0);

                    //Set angle and cast
                    if (ClockWise)
                        m_creature->SetOrientation(DarkGlareAngle + ((float)DarkGlareTick*PI/35));
                    else m_creature->SetOrientation(DarkGlareAngle - ((float)DarkGlareTick*PI/35));

                    m_creature->StopMoving();

                    //Actual dark glare cast, maybe something missing here?
                    m_creature->CastSpell(NULL, SPELL_DARK_GLARE, false);

                    //Increase tick
                    DarkGlareTick++;

                    //1 second per tick
                    DarkGlareTickTimer = 1000;
                }else DarkGlareTickTimer -= diff;

                //PhaseTimer
                if (PhaseTimer < diff)
                {
                    //Switch to Eye Beam
                    pInstance->SetData(DATA_CTHUN_PHASE, 0);

                    BeamTimer = 3000;
                    EyeTentacleTimer = 45000;               //Always spawns 5 seconds before Dark Beam
                    ClawTentacleTimer = 12500;              //4 per Eye beam phase (unsure if they spawn durring Dark beam)

                    m_creature->InterruptNonMeleeSpells(false);

                    //Remove Red coloration from c'thun
                    m_creature->RemoveAurasDueToSpell(SPELL_RED_COLORATION);

                    //Freeze animation
                    m_creature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);

                    //Eye Beam for 50 seconds
                    PhaseTimer = 50000;
                }else PhaseTimer -= diff;
            }break;

            //Transition phase
            case 2:
            {
                //Remove any target
                m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0);
                m_creature->SetHealth(0);
            }

            //Dead phase
            case 5:
            {
                m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false);
            }
        }
    }
Beispiel #16
0
        void UpdateAI(const uint32 diff)
        {
            if (!UpdateVictim())
                return;

            events.Update(diff);

            if (Phase == 1)
            {
                while (uint32 eventId = events.GetEvent())
                {
                    switch(eventId)
                    {
                        case EVENT_WASTE:
                            DoSummon(NPC_WASTE, Pos[RAND(0, 3, 6, 9)]);
                            events.RepeatEvent(urand(2000, 5000));
                            break;
                        case EVENT_ABOMIN:
                            if (nAbomination < 8)
                            {
                                DoSummon(NPC_ABOMINATION, Pos[RAND(1, 4, 7, 10)]);
                                nAbomination++;
                                events.RepeatEvent(20000);
                            }
                            else
                                events.PopEvent();
                            break;
                        case EVENT_WEAVER:
                            if (nWeaver < 8)
                            {
                                DoSummon(NPC_WEAVER, Pos[RAND(0, 3, 6, 9)]);
                                nWeaver++;
                                events.RepeatEvent(25000);
                            }
                            else
                                events.PopEvent();
                            break;
                        case EVENT_TRIGGER:
                            if (GameObject *pKTTrigger = me->GetMap()->GetGameObject(KTTriggerGUID))
                                pKTTrigger->SetPhaseMask(2, true);
                            events.PopEvent();
                            break;
                        case EVENT_PHASE:
                            events.Reset();
                            DoScriptText(RAND(SAY_AGGRO_1, SAY_AGGRO_2, SAY_AGGRO_3), me);
                            spawns.DespawnAll();
                            me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE);
                            me->CastStop();

                            DoStartMovement(me->getVictim());
                            events.ScheduleEvent(EVENT_BOLT, urand(5000, 10000));
                            events.ScheduleEvent(EVENT_NOVA, 15000);
                            events.ScheduleEvent(EVENT_DETONATE, urand(30000, 40000));
                            events.ScheduleEvent(EVENT_FISSURE, urand(10000, 30000));
                            events.ScheduleEvent(EVENT_BLAST, urand(60000, 120000));
                            if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)
                                events.ScheduleEvent(EVENT_CHAIN, urand(30000, 60000));
                            Phase = 2;
                            break;
                        default:
                            events.PopEvent();
                            break;
                    }
                }
            }
            else
            {
                //start phase 3 when we are 45% health
                if (Phase != 3)
                {
                    if (HealthBelowPct(45))
                    {
                        Phase = 3 ;
                        DoScriptText(SAY_REQUEST_AID, me);
                        //here Lich King should respond to KelThuzad but I don't know which Creature to make talk
                        //so for now just make Kelthuzad says it.
                        DoScriptText(SAY_ANSWER_REQUEST, me);

                        for (uint8 i = 0; i <= 3; ++i)
                        {
                            if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i]))
                            {
                                if (pPortal->getLootState() == GO_READY)
                                    pPortal->UseDoorOrButton();
                            }
                        }
                    }
                }
                else if (nGuardiansOfIcecrownCount < RAID_MODE(2, 4))
                {
                    if (uiGuardiansOfIcecrownTimer <= diff)
                    {
                        // TODO : Add missing text
                        if (Creature* pGuardian = DoSummon(NPC_ICECROWN, Pos[RAND(2, 5, 8, 11)]))
                            pGuardian->SetFloatValue(UNIT_FIELD_COMBATREACH, 2);
                        ++nGuardiansOfIcecrownCount;
                        uiGuardiansOfIcecrownTimer = 5000;
                    }
                    else uiGuardiansOfIcecrownTimer -= diff;
                }

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

                if (uint32 eventId = events.GetEvent())
                {
                    switch(eventId)
                    {
                        case EVENT_BOLT:
                            DoCastVictim(RAID_MODE(SPELL_FROST_BOLT, H_SPELL_FROST_BOLT));
                            events.RepeatEvent(urand(5000, 10000));
                            break;
                        case EVENT_NOVA:
                            DoCastAOE(RAID_MODE(SPELL_FROST_BOLT_AOE, H_SPELL_FROST_BOLT_AOE));
                            events.RepeatEvent(urand(15000, 30000));
                            break;
                        case EVENT_CHAIN:
                        {
                            uint32 count = urand(1, 3);
                            for (uint8 i = 1; i <= count; i++)
                            {
                                Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true);
                                if (pTarget && !pTarget->isCharmed() && (chained.find(pTarget->GetGUID()) == chained.end()))
                                {
                                    DoCast(pTarget, SPELL_CHAINS_OF_KELTHUZAD);
                                    float scale = pTarget->GetFloatValue(OBJECT_FIELD_SCALE_X);
                                    chained.insert(std::make_pair(pTarget->GetGUID(), scale));
                                    pTarget->SetFloatValue(OBJECT_FIELD_SCALE_X, scale * 2);
                                    events.ScheduleEvent(EVENT_CHAINED_SPELL, 2000); //core has 2000ms to set unit flag charm
                                }
                            }
                            if (!chained.empty())
                                DoScriptText(RAND(SAY_CHAIN_1, SAY_CHAIN_2), me);
                            events.RepeatEvent(urand(100000, 180000));
                            break;
                        }
                        case EVENT_CHAINED_SPELL:
                        {
                            std::map<uint64, float>::iterator itr;
                            for (itr = chained.begin(); itr != chained.end();)
                            {
                                if (Unit* player = Unit::GetPlayer(*me, (*itr).first))
                                {
                                    if (!player->isCharmed())
                                    {
                                        player->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second);
                                        std::map<uint64, float>::iterator next = itr;
                                        ++next;
                                        chained.erase(itr);
                                        itr = next;
                                        continue;
                                    }

                                    if (Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, NotCharmedTargetSelector()))
                                    {
                                        switch(player->getClass())
                                        {
                                            case CLASS_DRUID:
                                                if (urand(0, 1))
                                                    player->CastSpell(pTarget, SPELL_MOONFIRE, false);
                                                else
                                                    player->CastSpell(me, SPELL_LIFEBLOOM, false);
                                                break;
                                            case CLASS_HUNTER:
                                                player->CastSpell(pTarget, RAND(SPELL_MULTI_SHOT, SPELL_VOLLEY), false);
                                                break;
                                            case CLASS_MAGE:
                                                player->CastSpell(pTarget, RAND(SPELL_FROST_FIREBOLT, SPELL_ARCANE_MISSILES), false);
                                                break;
                                            case CLASS_WARLOCK:
                                                player->CastSpell(pTarget, RAND(SPELL_CURSE_OF_AGONY, SPELL_SHADOW_BOLT), true);
                                                break;
                                            case CLASS_WARRIOR:
                                                player->CastSpell(pTarget, RAND(SPELL_BLADESTORM, SPELL_CLEAVE), false);
                                                break;
                                            case CLASS_PALADIN:
                                                if (urand(0, 1))
                                                    player->CastSpell(pTarget, SPELL_HAMMER_OF_JUSTICE, false);
                                                else
                                                    player->CastSpell(me, SPELL_HOLY_SHOCK, false);
                                                break;
                                            case CLASS_PRIEST:
                                                if (urand(0, 1))
                                                    player->CastSpell(pTarget, SPELL_VAMPIRIC_TOUCH, false);
                                                else
                                                    player->CastSpell(me, SPELL_RENEW, false);
                                                break;
                                            case CLASS_SHAMAN:
                                                if (urand(0, 1))
                                                    player->CastSpell(pTarget, SPELL_EARTH_SHOCK, false);
                                                else
                                                    player->CastSpell(me, SPELL_HEALING_WAVE, false);
                                                break;
                                            case CLASS_ROGUE:
                                                player->CastSpell(pTarget, RAND(SPELL_HEMORRHAGE, SPELL_MUTILATE), false);
                                                break;
                                            case CLASS_DEATH_KNIGHT:
                                                if (urand(0, 1))
                                                    player->CastSpell(pTarget, SPELL_PLAGUE_STRIKE, true);
                                                else
                                                    player->CastSpell(pTarget, SPELL_HOWLING_BLAST, true);
                                                break;
                                        }
                                    }
                                }
                                ++itr;
                            }

                            if (chained.empty())
                                events.PopEvent();
                            else
                                events.RepeatEvent(5000);

                            break;
                        }
                        case EVENT_DETONATE:
                        {
                            std::vector<Unit*> unitList;
                            std::list<HostileReference*> *threatList = &me->getThreatManager().getThreatList();
                            for (std::list<HostileReference*>::const_iterator itr = threatList->begin(); itr != threatList->end(); ++itr)
                            {
                                if ((*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER
                                    && (*itr)->getTarget()->getPowerType() == POWER_MANA
                                    && (*itr)->getTarget()->GetPower(POWER_MANA))
                                    unitList.push_back((*itr)->getTarget());
                            }

                            if (!unitList.empty())
                            {
                                std::vector<Unit*>::const_iterator itr = unitList.begin();
                                advance(itr, rand()%unitList.size());
                                DoCast(*itr, SPELL_MANA_DETONATION);
                                DoScriptText(RAND(SAY_SPECIAL_1, SAY_SPECIAL_2, SAY_SPECIAL_3), me);
                            }

                            events.RepeatEvent(urand(20000, 50000));
                            break;
                        }
                        case EVENT_FISSURE:
                            if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0))
                                DoCast(pTarget, SPELL_SHADOW_FISURE);
                            events.RepeatEvent(urand(10000, 45000));
                            break;
                        case EVENT_BLAST:
                            if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, RAID_MODE(1, 0), 0, true))
                                DoCast(pTarget, SPELL_FROST_BLAST);
                            if (rand()%2)
                                DoScriptText(SAY_FROST_BLAST, me);
                            events.RepeatEvent(urand(30000, 90000));
                            break;
                        default:
                            events.PopEvent();
                            break;
                    }
                }

                DoMeleeAttackIfReady();
            }
        }
    void UpdateAI(const uint32 uiDiff)
    {
        if (m_bSummonKilrek)
        {
            if (m_uiSummonKilrekTimer < uiDiff)
            {
                if (DoCastSpellIfCan(m_creature, SPELL_SUMMON_IMP) == CAST_OK)
                {
                    m_uiSummonKilrekTimer = 45000;
                    m_bSummonKilrek = false;
                }
            }
            else
                m_uiSummonKilrekTimer -= uiDiff;
        }

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

        if (m_uiSacrifice_Timer < uiDiff)
        {
            Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1);
            if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER)
            {
                DoCastSpellIfCan(pTarget, SPELL_SACRIFICE, CAST_TRIGGERED);

                Creature* pChains = m_creature->SummonCreature(NPC_DEMONCHAINS, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 21000);
                if (pChains)
                {
                    ((mob_demon_chainAI*)pChains->AI())->m_uiSacrificeGUID = pTarget->GetGUID();
                    pChains->CastSpell(pChains, SPELL_DEMON_CHAINS, true);

                    DoScriptText(urand(0, 1) ? SAY_SACRIFICE1 : SAY_SACRIFICE2, m_creature);

                    m_uiSacrifice_Timer = 30000;
                }
            }
        }
        else
            m_uiSacrifice_Timer -= uiDiff;

        if (m_uiShadowbolt_Timer < uiDiff)
        {
            DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHADOW_BOLT);
            m_uiShadowbolt_Timer = 10000;
        }
        else
            m_uiShadowbolt_Timer -= uiDiff;

        if (!m_bSummonedPortals)
        {
            if (m_uiSummon_Timer < uiDiff)
            {
                if (DoCastSpellIfCan(m_creature, SPELL_FIENDISH_PORTAL, CAST_INTERRUPT_PREVIOUS) == CAST_OK)
                {
                    DoScriptText(urand(0, 1) ? SAY_SUMMON1 : SAY_SUMMON2, m_creature);
                    m_bSummonedPortals = true;
                }
            }
            else
                m_uiSummon_Timer -= uiDiff;
        }

        if (!m_bBerserk)
        {
            if (m_uiBerserk_Timer < uiDiff)
            {
                DoCastSpellIfCan(m_creature, SPELL_BERSERK, CAST_INTERRUPT_PREVIOUS);
                m_bBerserk = true;
            }
            else
                m_uiBerserk_Timer -= uiDiff;
        }

        DoMeleeAttackIfReady();
    }
Beispiel #18
0
void DynamicObject::UpdateTargets()
{
    if (!m_aliveDuration)
        return;

    if (m_aliveDuration >= 100)
    {
        Unit* target;
        Aura* pAura;

        float radius = m_floatValues[DYNAMICOBJECT_RADIUS] * m_floatValues[DYNAMICOBJECT_RADIUS];

        // Looking for targets in the Object set
        for (std::set< Object* >::iterator itr = m_objectsInRange.begin(); itr != m_objectsInRange.end(); ++itr)
        {
            Object* o = *itr;

            if (!o && !o->IsUnit() || !TO< Unit* >(o)->isAlive())
                continue;

            target = TO< Unit* >(o);

            if (!isAttackable(u_caster, target, !(m_spellProto->c_is_flags & SPELL_FLAG_IS_TARGETINGSTEALTHED)))
                continue;

            // skip units already hit, their range will be tested later
            if (targets.find(target->GetGUID()) != targets.end())
                continue;

            if (GetDistanceSq(target) <= radius)
            {
                pAura = sSpellFactoryMgr.NewAura(m_spellProto, m_aliveDuration, u_caster, target, true);
                for (uint8 i = 0; i < 3; i++)
                {
                    if (m_spellProto->Effect[i] == SPELL_EFFECT_PERSISTENT_AREA_AURA)
                    {
                        pAura->AddMod(m_spellProto->EffectApplyAuraName[i],
                            m_spellProto->EffectBasePoints[i] + 1, m_spellProto->EffectMiscValue[i], i);
                    }
                }
                target->AddAura(pAura);
                if (p_caster)
                {
                    p_caster->HandleProc(PROC_ON_CAST_SPECIFIC_SPELL | PROC_ON_CAST_SPELL, target, m_spellProto);
                    p_caster->m_procCounter = 0;
                }

                // add to target list
                targets.insert(target->GetGUID());
            }
        }

        // loop the targets, check the range of all of them
        DynamicObjectList::iterator jtr = targets.begin();
        DynamicObjectList::iterator jtr2;
        DynamicObjectList::iterator jend = targets.end();

        while (jtr != jend)
        {
            target = GetMapMgr() ? GetMapMgr()->GetUnit(*jtr) : NULL;
            jtr2 = jtr;
            ++jtr;

            if (target && GetDistanceSq(target) > radius)
            {
                target->RemoveAura(m_spellProto->Id);
                targets.erase(jtr2);
            }
        }

        m_aliveDuration -= 100;
    }
    else
        m_aliveDuration = 0;

    if (!m_aliveDuration)
        Remove();
}
Beispiel #19
0
 void HandleDummy(SpellEffIndex /*effIndex*/)
 {
     Unit* caster = GetCaster();
     if (Unit* target = GetHitUnit())
         m_multip = (target->GetDiseasesByCaster(caster->GetGUID()) * GetEffectValue()) / 100.0f;
 }
void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
{
    uint32 opcode = recv_data.GetOpcode();
    sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
    recv_data.hexlike();

    Unit *mover = _player->m_mover;
    Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL;

    // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
    if(plMover && plMover->IsBeingTeleported())
    {
        recv_data.rpos(recv_data.wpos());                   // prevent warnings spam
        return;
    }

    /* extract packet */
    uint64 guid;

    if(!recv_data.readPackGUID(guid))
        return;

    MovementInfo movementInfo;
    movementInfo.guid = guid;
    ReadMovementInfo(recv_data, &movementInfo);
    /*----------------*/

    if(!(movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) && _player->GetVehicleGUID())
    {
        if(mover->GetGUID() == _player->GetGUID())
        {
            return;
        }
    }
    // we sent a movement packet with MOVEMENTFLAG_ONTRANSPORT and we are on vehicle
    // this can be moving on vehicle or entering another transport (eg. boat)
    if((movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) && _player->GetVehicleGUID())
    {
        // we are controlling that vehicle
        if(mover->GetGUID() == _player->GetVehicleGUID())
        {
            // we sent movement packet, related to movement ON vehicle,
            // but not WITH vehicle, so mover = player
            if(_player->GetVehicleGUID() == movementInfo.t_guid)
            {
                // this is required to avoid client crash, otherwise it will result
                // in moving with vehicle on the same vehicle and that = crash
                mover = _player;
                plMover = _player;
            }
        }
        if(_player->GetVehicleGUID() == movementInfo.t_guid)
        {
            _player->m_SeatData.OffsetX = movementInfo.t_x;
            _player->m_SeatData.OffsetY = movementInfo.t_y;
            _player->m_SeatData.OffsetZ = movementInfo.t_z;
            _player->m_SeatData.Orientation = movementInfo.t_o;
        }
    }

        recv_data.rpos(recv_data.wpos());                   // prevent warnings spam
    if (!MaNGOS::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o))
    {
        recv_data.rpos(recv_data.wpos());                   // prevent warnings spam
        return;
    }

    /* handle special cases */
    if (movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && !mover->GetVehicleGUID())
    {
        // transports size limited
        // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
        if( movementInfo.t_x > 50 || movementInfo.t_y > 50 || movementInfo.t_z > 50 )
        {
            recv_data.rpos(recv_data.wpos());                   // prevent warnings spam
            return;
        }

        if( !MaNGOS::IsValidMapCoord(movementInfo.x+movementInfo.t_x, movementInfo.y + movementInfo.t_y,
            movementInfo.z + movementInfo.t_z, movementInfo.o + movementInfo.t_o) )
        {
            recv_data.rpos(recv_data.wpos());                   // prevent warnings spam
            return;
        }

        // if we boarded a transport, add us to it
        if (plMover && !plMover->m_transport)
        {
            // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list
            for (MapManager::TransportSet::const_iterator iter = sMapMgr.m_Transports.begin(); iter != sMapMgr.m_Transports.end(); ++iter)
            {
                if ((*iter)->GetGUID() == movementInfo.t_guid)
                {
                    plMover->m_transport = (*iter);
                    (*iter)->AddPassenger(plMover);
                    break;
                }
            }
        }
    }
    else if (plMover && plMover->m_transport)               // if we were on a transport, leave
    {
        plMover->m_transport->RemovePassenger(plMover);
        plMover->m_transport = NULL;
        movementInfo.t_x = 0.0f;
        movementInfo.t_y = 0.0f;
        movementInfo.t_z = 0.0f;
        movementInfo.t_o = 0.0f;
        movementInfo.t_time = 0;
        movementInfo.t_seat = -1;
    }

    // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
    if (opcode == MSG_MOVE_FALL_LAND && plMover && !plMover->isInFlight())
        plMover->HandleFall(movementInfo);

    if (plMover && (movementInfo.HasMovementFlag(MOVEMENTFLAG_SWIMMING) != plMover->IsInWater()))
    {
        // now client not include swimming flag in case jumping under water
        plMover->SetInWater( !plMover->IsInWater() || plMover->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) );
    }
    if (movementInfo.HasMovementFlag(MOVEMENTFLAG_SWIMMING))
    {
        if(mover->GetTypeId() == TYPEID_UNIT)
        {
            if(((Creature*)mover)->isVehicle() && !((Creature*)mover)->canSwim())
            {
                // NOTE : we should enter evade mode here, but...
                ((Vehicle*)mover)->SetSpawnDuration(1);
            }
        }
    }

    /*----------------------*/

    /* process position-change */
    WorldPacket data(opcode, recv_data.size());
    movementInfo.time = getMSTime();
    movementInfo.guid = mover->GetGUID();
    WriteMovementInfo(&data, &movementInfo);
    GetPlayer()->SendMessageToSet(&data, false);

    if(plMover)                                             // nothing is charmed, or player charmed
    {
        plMover->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
        plMover->m_movementInfo = movementInfo;
        plMover->UpdateFallInformationIfNeed(movementInfo, opcode);

        if(plMover->isMovingOrTurning())
            plMover->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);

        if(movementInfo.z < -500.0f)
        {
            if(plMover->InBattleGround()
                && plMover->GetBattleGround()
                && plMover->GetBattleGround()->HandlePlayerUnderMap(_player))
            {
                // do nothing, the handle already did if returned true
            }
            else
            {
                // NOTE: this is actually called many times while falling
                // even after the player has been teleported away
                // TODO: discard movement packets after the player is rooted
                if(plMover->isAlive())
                {
                    plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
                    // pl can be alive if GM/etc
                    if(!plMover->isAlive())
                    {
                        // change the death state to CORPSE to prevent the death timer from
                        // starting in the next player update
                        plMover->KillPlayer();
                        plMover->BuildPlayerRepop();
                    }
                }

                // cancel the death timer here if started
                plMover->RepopAtGraveyard();
            }
        }
    }
    else                                                    // creature charmed
    {
        if(mover->IsInWorld())
        {
            mover->GetMap()->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
            if(((Creature*)mover)->isVehicle())
                ((Vehicle*)mover)->RellocatePassengers(mover->GetMap());
        }
    }
}
void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data) {
	uint32 opcode = recv_data.GetOpcode();
	recv_data.hexlike();

	Unit *mover = _player->m_mover;

	ASSERT(mover != NULL); // there must always be a mover

	Player *plMover =
			mover->GetTypeId() == TYPEID_PLAYER ? (Player*) mover : NULL;

	// ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
	if (plMover && plMover->IsBeingTeleported()) {
		recv_data.rpos(recv_data.wpos()); // prevent warnings spam
		return;
	}

	/* extract packet */
	uint64 guid;

	recv_data.readPackGUID(guid);

	MovementInfo movementInfo;
	movementInfo.guid = guid;
	ReadMovementInfo(recv_data, &movementInfo);

	recv_data.rpos(recv_data.wpos()); // prevent warnings spam

	// prevent tampered movement data
	if (guid != mover->GetGUID())
		return;

	if (!movementInfo.pos.IsPositionValid()) {
		recv_data.rpos(recv_data.wpos()); // prevent warnings spam
		return;
	}

	/* handle special cases */
	if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) {
		// transports size limited
		// (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
		if (movementInfo.t_pos.GetPositionX() > 50
				|| movementInfo.t_pos.GetPositionY() > 50
				|| movementInfo.t_pos.GetPositionZ() > 50) {
			recv_data.rpos(recv_data.wpos()); // prevent warnings spam
			return;
		}

		if (!Trinity::IsValidMapCoord(
				movementInfo.pos.GetPositionX()
						+ movementInfo.t_pos.GetPositionX(),
				movementInfo.pos.GetPositionY()
						+ movementInfo.t_pos.GetPositionY(),
				movementInfo.pos.GetPositionZ()
						+ movementInfo.t_pos.GetPositionZ(),
				movementInfo.pos.GetOrientation()
						+ movementInfo.t_pos.GetOrientation())) {
			recv_data.rpos(recv_data.wpos()); // prevent warnings spam
			return;
		}

		// if we boarded a transport, add us to it
		if (plMover && !plMover->GetTransport()) {
			// elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list
			for (MapManager::TransportSet::const_iterator iter =
					sMapMgr->m_Transports.begin();
					iter != sMapMgr->m_Transports.end(); ++iter) {
				if ((*iter)->GetGUID() == movementInfo.t_guid) {
					plMover->m_transport = (*iter);
					(*iter)->AddPassenger(plMover);
					break;
				}
			}
		}

		if (!mover->GetTransport() && !mover->GetVehicle()) {
			GameObject *go = mover->GetMap()->GetGameObject(
					movementInfo.t_guid);
			if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT)
				movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT;
		}
	} else if (plMover && plMover->GetTransport()) // if we were on a transport, leave
			{
		plMover->m_transport->RemovePassenger(plMover);
		plMover->m_transport = NULL;
		movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
		movementInfo.t_time = 0;
		movementInfo.t_seat = -1;
	}

	// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
	if (opcode == MSG_MOVE_FALL_LAND && plMover && !plMover->isInFlight())
		plMover->HandleFall(movementInfo);

	if (plMover
			&& ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0)
					!= plMover->IsInWater()) {
		// now client not include swimming flag in case jumping under water
		plMover->SetInWater(
				!plMover->IsInWater()
						|| plMover->GetBaseMap()->IsUnderWater(
								movementInfo.pos.GetPositionX(),
								movementInfo.pos.GetPositionY(),
								movementInfo.pos.GetPositionZ()));
	}

	/*----------------------*/

	/* process position-change */
	WorldPacket data(opcode, recv_data.size());
	movementInfo.time = getMSTime();
	movementInfo.guid = mover->GetGUID();
	WriteMovementInfo(&data, &movementInfo);
	mover->SendMessageToSet(&data, _player);

	mover->m_movementInfo = movementInfo;

	// this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle()
	if (mover->GetVehicle()) {
		mover->SetOrientation(movementInfo.pos.GetOrientation());
		return;
	}

	mover->SetPosition(movementInfo.pos);

	if (plMover) // nothing is charmed, or player charmed
	{
		if (plMover->GetEmoteState() != 0 && opcode == MSG_MOVE_START_FORWARD
				&& opcode != MSG_MOVE_SET_FACING
				&& opcode != MSG_MOVE_START_TURN_LEFT
				&& opcode != MSG_MOVE_START_TURN_RIGHT
				&& opcode != MSG_MOVE_STOP_TURN)
			plMover->SetEmoteState(0);

		plMover->UpdateFallInformationIfNeed(movementInfo, opcode);

		if (movementInfo.pos.GetPositionZ() < -5000.0f) {
			if (!(plMover->InBattleground() && plMover->GetBattleground()
					&& plMover->GetBattleground()->HandlePlayerUnderMap(_player))) {
				// NOTE: this is actually called many times while falling
				// even after the player has been teleported away
				// TODO: discard movement packets after the player is rooted
				if (plMover->isAlive()) {
					plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID,
							GetPlayer()->GetMaxHealth());
					// pl can be alive if GM/etc
					if (!plMover->isAlive()) {
						// change the death state to CORPSE to prevent the death timer from
						// starting in the next player update
						plMover->KillPlayer();
						plMover->BuildPlayerRepop();
					}
				}

				// cancel the death timer here if started
				plMover->RepopAtGraveyard();
			}
		}
        else if (movementInfo.pos.GetPositionZ() < -50.0f)
        {
            if (plMover->InBattleground())
                if (Battleground* bg = plMover->GetBattleground())
                    if (bg->isArena())
                        bg->HandlePlayerUnderMap(_player);
        }		
	}
}
            void HandleDummy(SpellEffIndex /* effIndex */)
            {
                Unit* target = GetHitUnit();
                Unit* caster = GetCaster();

                target->CastSpell(target, roll_chance_i(50) ? SPELL_POSITIVE_POLARITY : SPELL_NEGATIVE_POLARITY, true, NULL, NULL, caster->GetGUID());
            }
Beispiel #23
0
            void HandleScriptEffect(SpellEffIndex /*effIndex*/)
            {
                Unit* caster = GetCaster();
                if (Unit* unitTarget = GetHitUnit())
                    if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x2, 0, 0, caster->GetGUID()))
                    {
                        Aura* aura = aurEff->GetBase();

                        uint32 countMin = aura->GetMaxDuration();
                        uint32 countMax = aura->GetSpellInfo()->GetMaxDuration() + 9000;
                        if (caster->HasAura(SPELL_DRUID_INCREASED_MOONFIRE_DURATION))
                            countMax += 3000;

                        if (countMin < countMax)
                        {
                            aura->SetDuration(uint32(aura->GetDuration() + 3000));
                            aura->SetMaxDuration(countMin + 3000);
                        }
                    }
            }
    void UpdateAI(const uint32 diff)
    {
        //Return since we have no target
        if (!UpdateVictim() )
            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: DoScriptText(SAY_SUMMON1, m_creature); break;
                    case 1: DoScriptText(SAY_SUMMON2, m_creature); break;
                }

                for(uint8 i = 0; i < 10; i++)
                {
                    Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0);
                    Creature* Murloc = m_creature->SummonCreature(MurlocCords[i][0],MurlocCords[i][1],MurlocCords[i][2],MurlocCords[i][3],MurlocCords[i][4], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000);
                    if(target && Murloc)
                        Murloc->AI()->AttackStart(target);
                }
                DoScriptText(EMOTE_EARTHQUAKE, m_creature);
                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;
                using std::set;
                set<int>list;
                set<int>::iterator itr;
                for(uint8 i = 0; i < 4; i++)
                {
                    counter = 0;
                    do{target = SelectUnit(SELECT_TARGET_RANDOM, 1, 50, true);    //target players only
                    if(counter < Playercount)
                        break;
                    if(target) itr = list.find(target->GetGUID());
                    counter++;
                    }while(itr != list.end());
                    if(target){list.insert(target->GetGUID());
                    ApplyWateryGrave(target, i);
                    }
                }

                switch(rand()%2)
                {
                    case 0: DoScriptText(SAY_SUMMON_BUBL1, m_creature); break;
                    case 1: DoScriptText(SAY_SUMMON_BUBL2, m_creature); break;
                }

                DoScriptText(EMOTE_WATERY_GRAVE, m_creature);
                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)
            {
                Unit* globuletarget;
                using std::set;
                set<int>globulelist;
                set<int>::iterator itr;
                for (int8 g = 0; g < 4; g++)  //one unit cant cast more than one spell per update, so some players have to cast for us XD
                {
                    counter = 0;
                    do {globuletarget = SelectUnit(SELECT_TARGET_RANDOM, 0,50,true);
                    if(globuletarget) itr = globulelist.find(globuletarget->GetGUID());
                    if (counter > Playercount)
                        break;
                    counter++;
                    } while (itr != globulelist.end());
                    if(globuletarget)globulelist.insert(globuletarget->GetGUID());
                    globuletarget->CastSpell(globuletarget, globulespell[g], true);
                }
                DoScriptText(EMOTE_WATERY_GLOBULES, m_creature);
                WateryGlobules_Timer = 25000;
            }else WateryGlobules_Timer -= diff;
        }

        DoMeleeAttackIfReady();
    }
Beispiel #25
0
        void UpdateAI(const uint32 uiDiff)
        {
            if (!UpdateVictim())
                return;

            switch (m_uiStage)
            {
                case 0:
                    if (m_uiFerociousButtTimer <= uiDiff)
                    {
                        DoCastVictim(SPELL_FEROCIOUS_BUTT);
                        m_uiFerociousButtTimer = urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS);
                    } else m_uiFerociousButtTimer -= uiDiff;

                    if (m_uiArticBreathTimer <= uiDiff)
                    {
                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
                            DoCast(target, SPELL_ARCTIC_BREATH);
                        m_uiArticBreathTimer = urand(25*IN_MILLISECONDS, 40*IN_MILLISECONDS);
                    } else m_uiArticBreathTimer -= uiDiff;

                    if (m_uiWhirlTimer <= uiDiff)
                    {
                        DoCastAOE(SPELL_WHIRL);
                        m_uiWhirlTimer = urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS);
                    } else m_uiWhirlTimer -= uiDiff;

                    if (m_uiMassiveCrashTimer <= uiDiff)
                    {
                        me->GetMotionMaster()->MoveJump(ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 10.0f, 20.0f); // 1: Middle of the room
                        m_uiStage = 7; //Invalid (Do nothing more than move)
                        m_uiMassiveCrashTimer = 30*IN_MILLISECONDS;
                    } else m_uiMassiveCrashTimer -= uiDiff;

                    DoMeleeAttackIfReady();
                    break;
                case 1:
                    DoCastAOE(SPELL_MASSIVE_CRASH);
                    m_uiStage = 2;
                    break;
                case 2:
                    if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true))
                    {
                        m_uiTrampleTargetGUID = target->GetGUID();
                        me->SetTarget(m_uiTrampleTargetGUID);
                        DoScriptText(SAY_TRAMPLE_STARE, me, target);
                        m_bTrampleCasted = false;
                        SetCombatMovement(false);
                        me->GetMotionMaster()->MoveIdle();
                        me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                        m_uiTrampleTimer = 4*IN_MILLISECONDS;
                        m_uiStage = 3;
                    } else m_uiStage = 6;
                    break;
                case 3:
                    if (m_uiTrampleTimer <= uiDiff)
                    {
                        if (Unit* target = Unit::GetPlayer(*me, m_uiTrampleTargetGUID))
                        {
                            m_bTrampleCasted = false;
                            m_bMovementStarted = true;
                            m_fTrampleTargetX = target->GetPositionX();
                            m_fTrampleTargetY = target->GetPositionY();
                            m_fTrampleTargetZ = target->GetPositionZ();
                            me->GetMotionMaster()->MoveJump(2*me->GetPositionX()-m_fTrampleTargetX,
                                2*me->GetPositionY()-m_fTrampleTargetY,
                                me->GetPositionZ(),
                                10.0f, 20.0f); // 2: Hop Backwards
                            m_uiStage = 7; //Invalid (Do nothing more than move)
                        } else m_uiStage = 6;
                    } else m_uiTrampleTimer -= uiDiff;
                    break;
                case 4:
                    DoScriptText(SAY_TRAMPLE_START, me);
                    me->GetMotionMaster()->MoveCharge(m_fTrampleTargetX, m_fTrampleTargetY, m_fTrampleTargetZ+2, 42, 1);
                    me->SetTarget(0);
                    m_uiStage = 5;
                    break;
                case 5:
                    if (m_bMovementFinish)
                    {
                        if (m_uiTrampleTimer <= uiDiff) DoCastAOE(SPELL_TRAMPLE);
                        m_bMovementFinish = false;
                        m_uiStage = 6;
                        return;
                    }
                    if (m_uiTrampleTimer <= uiDiff)
                    {
                        Map::PlayerList const &lPlayers = me->GetMap()->GetPlayers();
                        for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr)
                        {
                            if (Unit* player = itr->getSource())
                                if (player->isAlive() && player->IsWithinDistInMap(me, 6.0f))
                                {
                                    DoCastAOE(SPELL_TRAMPLE);
                                    m_uiTrampleTimer = IN_MILLISECONDS;
                                    break;
                                }
                        }
                    } else m_uiTrampleTimer -= uiDiff;
                    break;
                case 6:
                    if (!m_bTrampleCasted)
                    {
                        DoCast(me, SPELL_STAGGERED_DAZE);
                        DoScriptText(SAY_TRAMPLE_FAIL, me);
                    }
                    m_bMovementStarted = false;
                    me->GetMotionMaster()->MovementExpired();
                    me->GetMotionMaster()->MoveChase(me->getVictim());
                    SetCombatMovement(true);
                    me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    m_uiStage = 0;
                    break;
            }
        }
Beispiel #26
0
            void UpdateAI(const uint32 Diff)
            {
                if (!UpdateVictim())
                    return;

                if (!_bIsPhaseTwo)
                {
                    if (ShadowWordPain_Timer <= Diff)
                    {
                        DoCast(me->getVictim(), SPELL_SHADOWWORDPAIN);
                        ShadowWordPain_Timer = 15000;
                    }
                    else
                        ShadowWordPain_Timer -= Diff;

                    if (Mark_Timer <= Diff)
                    {
                        Unit* markedTarget = SelectTarget(SELECT_TARGET_RANDOM, 0);

                        if (markedTarget)
                        {
                            DoCast(markedTarget, SPELL_MARK);
                            MarkedTargetGUID = markedTarget->GetGUID();
                        }
                        else
                            sLog->outError("TSCR: boss_arlokk could not accuire MarkedTarget.");

                        Mark_Timer = 15000;
                    }
                    else
                        Mark_Timer -= Diff;
                }
                else
                {
                    //Cleave_Timer
                    if (Cleave_Timer <= Diff)
                    {
                        DoCast(me->getVictim(), SPELL_CLEAVE);
                        Cleave_Timer = 16000;
                    }
                    else
                        Cleave_Timer -= Diff;

                    //Gouge_Timer
                    if (Gouge_Timer <= Diff)
                    {
                        DoCast(me->getVictim(), SPELL_GOUGE);

                        DoModifyThreatPercent(me->getVictim(), -80);

                        Gouge_Timer = 17000+rand()%10000;
                    }
                    else
                        Gouge_Timer -= Diff;
                }

                if (SummonCount <= 30)
                {
                    if (Summon_Timer <= Diff)
                    {
                        DoSummonPhanters();
                        Summon_Timer = 5000;
                    }
                    else
                        Summon_Timer -= Diff;
                }

                if (Vanish_Timer <= Diff)
                {
                    //Invisble Model
                    me->SetDisplayId(MODEL_ID_BLANK);
                    me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);

                    me->AttackStop();
                    DoResetThreat();

                    _bIsVanished = true;

                    Vanish_Timer  = 45000;
                    Visible_Timer = 6000;
                }
                else
                    Vanish_Timer -= Diff;

                if (_bIsVanished)
                {
                    if (Visible_Timer <= Diff)
                    {
                        //The Panther Model
                        me->SetDisplayId(MODEL_ID_PANTHER);
                        me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);

                        const CreatureTemplate* cinfo = me->GetCreatureInfo();
                        me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35)));
                        me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35)));
                        me->UpdateDamagePhysical(BASE_ATTACK);

                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
                            AttackStart(target);

                        _bIsPhaseTwo = true;
                        _bIsVanished = false;
                    }
                    else
                        Visible_Timer -= Diff;
                }
                else
                    DoMeleeAttackIfReady();
            }
            void UpdateAI(uint32 const diff)
            {
                if (!UpdateVictim() || !CheckInRoom())
                    return;

                events.Update(diff);

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

                while (uint32 eventId = events.ExecuteEvent())
                {
                    switch (eventId)
                    {
                        case EVENT_BERSERK:
                            DoScriptText(EMOTE_GENERIC_BERSERK_RAID, me);
                            Talk(SAY_BERSERK);
                            DoCast(me, SPELL_BERSERK);
                            break;
                        case EVENT_VAMPIRIC_BITE:
                        {
                            std::list<Player*> targets;
                            SelectRandomTarget(false, &targets);
                            if (!targets.empty())
                            {
                                Unit* target = targets.front();
                                DoCast(target, SPELL_VAMPIRIC_BITE);
                                Talk(SAY_VAMPIRIC_BITE);
                                _vampires.insert(target->GetGUID());
                            }
                            break;
                        }
                        case EVENT_BLOOD_MIRROR:
                        {
                            // victim can be NULL when this is processed in the same update tick as EVENT_AIR_PHASE
                            if (me->getVictim())
                            {
                                Player* newOfftank = SelectRandomTarget(true);
                                if (_offtank != newOfftank)
                                {
                                    _offtank = newOfftank;
                                    if (_offtank)
                                    {
                                        // both spells have SPELL_ATTR5_SINGLE_TARGET_SPELL, no manual removal needed
                                        _offtank->CastSpell(me->getVictim(), SPELL_BLOOD_MIRROR_DAMAGE, true);
                                        me->getVictim()->CastSpell(_offtank, SPELL_BLOOD_MIRROR_DUMMY, true);
                                        DoCastVictim(SPELL_BLOOD_MIRROR_VISUAL);
                                        if (Item* shadowsEdge = _offtank->GetWeaponForAttack(BASE_ATTACK, true))
                                            if (!_offtank->HasAura(SPELL_THIRST_QUENCHED) && shadowsEdge->GetEntry() == ITEM_SHADOW_S_EDGE && !_offtank->HasAura(SPELL_GUSHING_WOUND))
                                                _offtank->CastSpell(_offtank, SPELL_GUSHING_WOUND, true);

                                    }
                                }
                            }
                            events.ScheduleEvent(EVENT_BLOOD_MIRROR, 2500, EVENT_GROUP_CANCELLABLE);
                            break;
                        }
                        case EVENT_DELIRIOUS_SLASH:
                            if (_offtank && !me->HasByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER))
                                DoCast(_offtank, SPELL_DELIRIOUS_SLASH);
                            events.ScheduleEvent(EVENT_DELIRIOUS_SLASH, urand(20000, 24000), EVENT_GROUP_NORMAL);
                            break;
                        case EVENT_PACT_OF_THE_DARKFALLEN:
                        {
                            std::list<Player*> targets;
                            SelectRandomTarget(false, &targets);
                            uint32 targetCount = 2;
                            // do not combine these checks! we want it incremented TWICE when both conditions are met
                            if (IsHeroic())
                                ++targetCount;
                            if (Is25ManRaid())
                                ++targetCount;
                            Trinity::RandomResizeList<Player*>(targets, targetCount);
                            if (targets.size() > 1)
                            {
                                Talk(SAY_PACT_OF_THE_DARKFALLEN);
                                for (std::list<Player*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
                                    DoCast(*itr, SPELL_PACT_OF_THE_DARKFALLEN);
                            }
                            events.ScheduleEvent(EVENT_PACT_OF_THE_DARKFALLEN, 30500, EVENT_GROUP_NORMAL);
                            break;
                        }
                        case EVENT_SWARMING_SHADOWS:
                            if (Player* target = SelectRandomTarget(false))
                            {
                                Talk(EMOTE_SWARMING_SHADOWS, target->GetGUID());
                                Talk(SAY_SWARMING_SHADOWS);
                                DoCast(target, SPELL_SWARMING_SHADOWS);
                            }
                            events.ScheduleEvent(EVENT_SWARMING_SHADOWS, 30500, EVENT_GROUP_NORMAL);
                            break;
                        case EVENT_TWILIGHT_BLOODBOLT:
                        {
                            std::list<Player*> targets;
                            SelectRandomTarget(false, &targets);
                            Trinity::RandomResizeList<Player*>(targets, uint32(Is25ManRaid() ? 4 : 2));
                            for (std::list<Player*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
                                DoCast(*itr, SPELL_TWILIGHT_BLOODBOLT);
                            DoCast(me, SPELL_TWILIGHT_BLOODBOLT_TARGET);
                            events.ScheduleEvent(EVENT_TWILIGHT_BLOODBOLT, urand(10000, 15000), EVENT_GROUP_NORMAL);
                            break;
                        }
                        case EVENT_AIR_PHASE:
                            DoStopAttack();
                            me->SetReactState(REACT_PASSIVE);
                            events.DelayEvents(10000, EVENT_GROUP_NORMAL);
                            events.CancelEventGroup(EVENT_GROUP_CANCELLABLE);
                            me->GetMotionMaster()->MovePoint(POINT_CENTER, centerPos);
                            break;
                        case EVENT_AIR_START_FLYING:
                            me->SetDisableGravity(true);
                            me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND);
                            me->SetCanFly(true);
                            me->SendMovementFlagUpdate();
                            me->GetMotionMaster()->MovePoint(POINT_AIR, airPos);
                            break;
                        case EVENT_AIR_FLY_DOWN:
                            me->GetMotionMaster()->MovePoint(POINT_GROUND, centerPos);
                            break;
                        default:
                            break;
                    }
                }

                DoMeleeAttackIfReady();
            }
Beispiel #28
0
            void UpdateAI(const uint32 diff)
            {
                if (!UpdateVictim())
                    return;

                events.Update(diff);
                _DoAggroPulse(diff);

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

                switch (events.GetEvent())
                {
                    case EVENT_MELEE_CHECK:
                        if (!me->IsWithinMeleeRange(me->getVictim()))
                            DoCast(SPELL_PETRIFY_BREATH);
                        events.RepeatEvent(1000);
                        break;
                    case EVENT_SWEEP:
                        if (left)
                        {
                            DoCast(SPELL_ARM_SWEEP);
                            DoScriptText(SAY_SHOCKWAVE, me);
                        }
                        events.RepeatEvent(25000);
                        break;
                    case EVENT_SMASH:
                        if (left && right)
                            DoCastVictim(SPELL_TWO_ARM_SMASH);
                        else if (left || right)
                            DoCastVictim(SPELL_ONE_ARM_SMASH);
                        events.RepeatEvent(urand(8000, 10000));
                        break;
                    case EVENT_STONE_SHOUT:
                        DoCast(SPELL_STONE_SHOUT);
                        events.RepeatEvent(2000);
                        break;
                    case EVENT_ENRAGE:
                        DoCast(SPELL_BERSERK);
                        DoScriptText(SAY_BERSERK, me);
                        events.CancelEvent(EVENT_ENRAGE);
                        break;
                    case EVENT_RESPAWN_LEFT_ARM:
                    {
                        RespawnArm(NPC_LEFT_ARM);
                        me->MonsterTextEmote(EMOTE_LEFT, 0, true);
                        events.CancelEvent(EVENT_RESPAWN_LEFT_ARM);
                        break;
                    }
                    case EVENT_RESPAWN_RIGHT_ARM:
                    {
                        RespawnArm(NPC_RIGHT_ARM);
                        me->MonsterTextEmote(EMOTE_RIGHT, 0, true);
                        events.CancelEvent(EVENT_RESPAWN_RIGHT_ARM);
                        break;
                    }
                    case EVENT_STONE_GRIP:
                    {
                        if (right)
                        {
                            DoCast(SPELL_STONE_GRIP);
                            me->MonsterTextEmote(EMOTE_STONE, 0, true);
                            DoScriptText(SAY_GRAB_PLAYER, me);
                        }
                        events.RepeatEvent(25000);
                        break;
                    }
					case EVENT_SHOCKWAVE:
						if (left)
						{
							DoScriptText(SAY_SHOCKWAVE, me);
							DoCastAOE(SPELL_SHOCKWAVE, true);
							DoCastAOE(SPELL_SHOCKWAVE_VISUAL, true);
						}
						events.RepeatEvent(urand(15000, 25000));
						break;
                    case EVENT_FOCUSED_EYEBEAM:
                        Unit* eyebeamTargetUnit = GetEyeBeamTarget();
                        if (!eyebeamTargetUnit)
                            eyebeamTargetUnit = SelectTarget(SELECT_TARGET_RANDOM, 0, 60.0f, true, -SPELL_STONE_GRIP_DOT);
                        if (eyebeamTargetUnit)
                        {
                            eyebeamTarget = eyebeamTargetUnit->GetGUID();
                            me->MonsterWhisper(EMOTE_EYEBEAM, eyebeamTarget, true);
                            DoCast(SPELL_SUMMON_FOCUSED_EYEBEAM);
                        }
                        events.RepeatEvent(urand(15000, 35000));
                        break;
                }

                DoMeleeAttackIfReady();
            }
Beispiel #29
0
bool PetAI::CanAttack(Unit* target)
{
    // Evaluates wether a pet can attack a specific target based on CommandState, ReactState and other flags
    // IMPORTANT: The order in which things are checked is important, be careful if you add or remove checks

    // Hmmm...
    if (!target)
        return false;

    // If pet disabled dont start attack (for example owner in mount)
    if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED) && !me->HasUnitState(UNIT_STATE_STUNNED))
        return false;

    if (!target->IsAlive())
    {
        // Clear target to prevent getting stuck on dead targets
        me->AttackStop();
        me->InterruptNonMeleeSpells(false);
        me->SendMeleeAttackStop();
        return false;
    }

    // Passive - passive pets can attack if told to
    if (me->HasReactState(REACT_PASSIVE))
        return me->GetCharmInfo()->IsCommandAttack();

    // CC - mobs under crowd control can be attacked if owner commanded
    if (target->HasCrowdControlAura())
        return me->GetCharmInfo()->IsCommandAttack();

    // Returning - pets ignore attacks only if owner clicked follow
    if (me->GetCharmInfo()->IsReturning())
        return !me->GetCharmInfo()->IsCommandFollow();

    // Stay - can attack if target is within range or commanded to
    if (me->GetCharmInfo()->HasCommandState(COMMAND_STAY))
        return (me->IsWithinMeleeRange(target) || me->GetCharmInfo()->IsCommandAttack());

    if (me->HasReactState(REACT_ASSIST))
    {
        Unit* ownerTarget = NULL;
        if (Player* owner = me->GetCharmerOrOwner()->ToPlayer())
            ownerTarget = owner->GetSelectedUnit();
        else
            ownerTarget = me->GetCharmerOrOwner()->GetVictim();

        if (target != ownerTarget)
            return false;
    }

    //  Pets attacking something (or chasing) should only switch targets if owner tells them to
    if (me->GetVictim() && me->GetVictim() != target)
    {
        // Check if our owner selected this target and clicked "attack"
        Unit* ownerTarget = NULL;
        if (Player* owner = me->GetCharmerOrOwner()->ToPlayer())
            ownerTarget = owner->GetSelectedUnit();
        else
            ownerTarget = me->GetCharmerOrOwner()->GetVictim();

        if (ownerTarget && me->GetCharmInfo()->IsCommandAttack())
            return (target->GetGUID() == ownerTarget->GetGUID());
    }

    // Follow
    if (me->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
        return !me->GetCharmInfo()->IsReturning();

    // default, though we shouldn't ever get here
    return false;
}
void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
{
    uint16 opcode = recvData.GetOpcode();

    Unit* mover = _player->m_mover;

    ASSERT(mover != NULL);                      // there must always be a mover

    Player* plrMover = mover->ToPlayer();

    // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
    if (plrMover && plrMover->IsBeingTeleported())
    {
        recvData.rfinish();                     // prevent warnings spam
        return;
    }

    /* extract packet */
    uint64 guid;

    recvData.readPackGUID(guid);

    MovementInfo movementInfo;
    movementInfo.guid = guid;
    ReadMovementInfo(recvData, &movementInfo);

    recvData.rfinish();                         // prevent warnings spam

    // prevent tampered movement data
    if (guid != mover->GetGUID())
        return;

    if (!movementInfo.pos.IsPositionValid())
    {
        recvData.rfinish();                     // prevent warnings spam
        return;
    }

    /* handle special cases */
    if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT)
    {
        // transports size limited
        // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
        if (movementInfo.transport.pos.GetPositionX() > 50 || movementInfo.transport.pos.GetPositionY() > 50 || movementInfo.transport.pos.GetPositionZ() > 50)
        {
            recvData.rfinish();                 // prevent warnings spam
            return;
        }

        if (!Trinity::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(),
            movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation()))
        {
            recvData.rfinish();                 // prevent warnings spam
            return;
        }

        // if we boarded a transport, add us to it
        if (plrMover)
        {
            if (!plrMover->GetTransport())
            {
                if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid))
                {
                    plrMover->m_transport = transport;
                    transport->AddPassenger(plrMover);
                }
            }
            else if (plrMover->GetTransport()->GetGUID() != movementInfo.transport.guid)
            {
                bool foundNewTransport = false;
                plrMover->m_transport->RemovePassenger(plrMover);
                if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid))
                {
                    foundNewTransport = true;
                    plrMover->m_transport = transport;
                    transport->AddPassenger(plrMover);
                }

                if (!foundNewTransport)
                {
                    plrMover->m_transport = NULL;
                    movementInfo.transport.Reset();
                }
            }
        }

        if (!mover->GetTransport() && !mover->GetVehicle())
        {
            GameObject* go = mover->GetMap()->GetGameObject(movementInfo.transport.guid);
            if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT)
                movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT;
        }
    }
    else if (plrMover && plrMover->GetTransport())                // if we were on a transport, leave
    {
        plrMover->m_transport->RemovePassenger(plrMover);
        plrMover->m_transport = NULL;
        movementInfo.transport.Reset();
    }

    // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
    if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight())
        plrMover->HandleFall(movementInfo);

    if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater())
    {
        // now client not include swimming flag in case jumping under water
        plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ()));
    }

    uint32 mstime = getMSTime();
    /*----------------------*/
    if (m_clientTimeDelay == 0)
        m_clientTimeDelay = mstime - movementInfo.time;

    /* process position-change */
    WorldPacket data(opcode, recvData.size());
    movementInfo.time = movementInfo.time + m_clientTimeDelay + MOVEMENT_PACKET_TIME_DELAY;

    movementInfo.guid = mover->GetGUID();
    WriteMovementInfo(&data, &movementInfo);
    mover->SendMessageToSet(&data, _player);

    mover->m_movementInfo = movementInfo;

    // this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle()
    if (mover->GetVehicle())
    {
        mover->SetOrientation(movementInfo.pos.GetOrientation());
        return;
    }

    mover->UpdatePosition(movementInfo.pos);

    if (plrMover)                                            // nothing is charmed, or player charmed
    {
        plrMover->UpdateFallInformationIfNeed(movementInfo, opcode);

        if (movementInfo.pos.GetPositionZ() < -500.0f)
        {
            if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player)))
            {
                // NOTE: this is actually called many times while falling
                // even after the player has been teleported away
                /// @todo discard movement packets after the player is rooted
                if (plrMover->IsAlive())
                {
                    plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
                    // player can be alive if GM/etc
                    // change the death state to CORPSE to prevent the death timer from
                    // starting in the next player update
                    if (!plrMover->IsAlive())
                        plrMover->KillPlayer();
                }
            }
        }
    }
}