bool PlayerbotDruidAI::RezTarget (Unit *target)
{
    if(!target || target->isAlive()) return false;
    Player *m_bot = GetPlayerBot();
    if (target->IsNonMeleeSpellCasted(true)) { return false; } //Already resurrected

    if (m_bot->isInCombat())
    {
        if (!CanCast(REBIRTH,target)) return false;
        Unit *m_tank = FindMainTankInRaid(m_bot);
        if (!m_tank) m_tank = m_bot;
        if (target->GetGUID() != m_tank->GetGUID() &&
            (target->getClass() != (uint8) CLASS_PRIEST || target->getClass() != (uint8) CLASS_DRUID || target->getClass() != (uint8) CLASS_PALADIN) ) return false;
        std::string msg = "Rezzing ";
        msg += target->GetName();
       // msg += " with ";
       // msg += *REZZSpell->SpellName;
        GetPlayerBot()->Say(msg, LANG_UNIVERSAL);
        return CastSpell(REBIRTH, target);
    }
    else
    {
        if (!CanCast(REVIVE,target)) return false;
        std::string msg = "Rezzing ";
        msg += target->GetName();
       // msg += " with ";
       // msg += *REZZSpell->SpellName;
        GetPlayerBot()->Say(msg, LANG_UNIVERSAL);
        return CastSpell(REVIVE, target);
    }
    return false;
}
bool PlayerbotDruidAI::HealTarget(Unit *target, uint8 hp)
{
    PlayerbotAI *ai = GetAI();
    Player *m_bot = GetPlayerBot();
    if (!m_bot || !ai || m_bot->isDead()) { return false; }
    if (!target || target->isDead()) { return false; }

    // Decide if it is worth to change form
    if (ai->GetForm() == FORM_MOONKIN || ai->GetForm() == FORM_CAT || ai->GetForm() == FORM_DIREBEAR || ai->GetForm() == FORM_BEAR)
    {
        if (hp < 75 && GetAI()->GetManaPercent() >= 70 ) { ChangeForm(1); }
        else if (hp < 40 && GetAI()->GetManaPercent() >= 50) { ChangeForm(1); }
        else if (hp < 25 && GetAI()->GetManaPercent() >= 30) { ChangeForm(1); }
        else return false;
    }

    // if(m_bot->HasAura(TRAVEL_FORM)) ChangeForm(1);

    if(hp < 60 && m_bot->HasAura(NATURES_SWIFTNESS) && CastSpell(HEALING_TOUCH, target)) { return true; }
    if(hp < 90 && CastSpell(LIFEBLOOM, target)) { return true; }
    if(hp < 80 && CastSpell(REJUVENATION, target)) { return true; }
    if(hp < 60 && CastSpell(REGROWTH, target)) { return true; }
    if(hp < 70 && CanCast(NOURISH,target) &&
        (HasAuraName(target,REJUVENATION,m_bot->GetGUID()) || HasAuraName(target,LIFEBLOOM,m_bot->GetGUID()) || HasAuraName(target,REGROWTH,m_bot->GetGUID()))
        ) { return CastSpell(NOURISH, target, false); }
    if(hp < 50 && CanCast(SWIFTMEND,target) &&
        (HasAuraName(target,REJUVENATION,m_bot->GetGUID()) || HasAuraName(target,REGROWTH,m_bot->GetGUID()))
        ) { return CastSpell(SWIFTMEND, target, false); }
    if(hp < 40 && m_bot->isInCombat() && CastSpell(NATURES_SWIFTNESS, m_bot)) { } // NO gcd
    if(hp < 40 && CastSpell(HEALING_TOUCH, target)) { return true; }
    return false;
} //end HealTarget
bool PlayerbotDruidAI::HealGroup(Unit *target, uint8 hp, uint8 &countNeedHeal)
{
    PlayerbotAI *ai = GetAI();
    Player *m_bot = GetPlayerBot();
    if (!m_bot || !ai || m_bot->isDead()) { return false; }
    if (!target || target->isDead()) { return false; }

    if (countNeedHeal < 2) { return false; }

    // Decide if it is worth to change form
    if (ai->GetForm() == FORM_MOONKIN || ai->GetForm() == FORM_CAT || ai->GetForm() == FORM_DIREBEAR || ai->GetForm() == FORM_BEAR)
    {
        if (hp > 70) { return false; }
        if (!CanCast(TRANQUILITY,target,0,0,1) && !WILD_GROWTH) { return false; }
        if (!WILD_GROWTH && hp > 35) { return false; }
        if (hp < 65 && GetAI()->GetManaPercent() >= 70 ) { ChangeForm(1); }
        else if (hp < 40 && GetAI()->GetManaPercent() >= 50) { ChangeForm(1); }
        else if (hp < 25 && GetAI()->GetManaPercent() >= 30) { ChangeForm(1); }
        else return false;
    }

    if (hp < 36 && m_bot->isInCombat() && CanCast(TRANQUILITY,target))
    {
            bool sc = CastSpell(TRANQUILITY, target, false);
            if (sc) GetAI()->SetIgnoreUpdateTime(10);
            return sc;
    }
    if (hp < 75 && CastSpell(WILD_GROWTH,target)) { return true; }
    return false;
}
bool PlayerbotShamanAI::HealTarget(Unit *target, uint8 hp)
{
    if(!target || target->isDead()) return false;
    Player *m_bot = GetPlayerBot();

    if(hp < 30 && m_bot->isInCombat() && CastSpell(NATURES_SWIFTNESS, m_bot)) {} // NO gcd
    if(hp < 60 && CanCast(HEAL,target,true) && m_bot->HasAura(NATURES_SWIFTNESS) && CastSpell(HEAL, target, false)) {
        return true;
    }
    if(hp < 30 && CastSpell(LESSER_HEAL,target,true,true)) {
        return true;
    }
    if(hp < 40 && m_bot->getRace() == (uint8) RACE_DRAENEI && CastSpell(R_GIFT_OF_NAARU,target)) {} // no GCD
    if(hp < 65 && CanCast(EARTH_SHIELD,target) && !m_bot->HasAura(EARTH_SHIELD,m_bot->GetGUID()) && CastSpell(EARTH_SHIELD,target,false)) {
        return true;
    }
    if(hp < 65 && CastSpell(HEAL,target,true,true)) {
        return true;
    }
    if(hp < 85 && CastSpell(LESSER_HEAL,target,true,true)) {
        return true;
    }

    return false;
} //end HealTarget
bool PlayerbotDruidAI::BuffPlayer(Unit *target)
{
    PlayerbotAI *ai = GetAI();
    Player *m_bot = GetPlayerBot();
    if (!m_bot || !ai || m_bot->isDead()) { return false; }

    if(!target || target->isDead()) { return false; }

    if (CanCast(THORNS,target,0,0,1) && !HasAuraName(target, THORNS)) {
        // Decide if it is worth to change form
        if( /*m_bot->HasAura(MOONKIN_FORM) ||*/ m_bot->HasAura(CAT_FORM) || m_bot->HasAura(BEAR_FORM))
        {
            if(GetAI()->GetManaPercent() >= 80 ) { ChangeForm(1); }
            else { return false; }
        }
        return CastSpell(THORNS, target, false);
    }
    if (CanCast(MARK_OF_THE_WILD,target,0,0,1) && !HasAuraName(target, GIFT_OF_THE_WILD) && !HasAuraName(target, MARK_OF_THE_WILD)) {
        // Decide if it is worth to change form
        if(/*m_bot->HasAura(MOONKIN_FORM) ||*/ m_bot->HasAura(CAT_FORM) || m_bot->HasAura(BEAR_FORM))
        {
            if(GetAI()->GetManaPercent() >= 70 ) { ChangeForm(1); }
            else return false;
        }
        return CastSpell(MARK_OF_THE_WILD, target, false);
    }
    return false;
}
	void ToggleVisibility()
	{
		mAddsSpawned = !mAddsSpawned;

		if(mAddsSpawned)
		{
			if(CanCast(m_creature, GetSpellStore()->LookupEntry(17651)) == false) //CC check
			{
				mAddsSpawned = !mAddsSpawned;
				return;
			}

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

			m_creature->SummonCreature(11263, x + 0, y + 0, z, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN_FORCED, 10000);
			m_creature->SummonCreature(11263, x + 5, y + 0, z, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN_FORCED, 10000);
			m_creature->SummonCreature(11263, x + 0, y + 5, z, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN_FORCED, 10000);
			m_creature->SummonCreature(11263, x - 5, y + 0, z, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN_FORCED, 10000);
			m_creature->SummonCreature(11263, x + 0, y - 5, z, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN_FORCED, 10000);
			m_creature->SetVisibility(UnitVisibility::VISIBILITY_OFF);
			m_creature->RemoveAllAuras();
			mImageProjectionTimer = 10000;
		}
		else
		{
			mImageProjectionTimer = 12000;
			m_creature->SetVisibility(UnitVisibility::VISIBILITY_ON);
		}
	}
bool PlayerbotDruidAI::ChangeForm(uint32 form)
{
    PlayerbotAI *ai = GetAI();
    Player *m_bot = GetPlayerBot();
    if (!m_bot || !ai || m_bot->isDead()) { return false; }
    if (!form) return false;

    if (form == 1 && ai->GetForm() == FORM_NONE) return false;

    if (form != 1)
    {
        if (!CanCast(form,m_bot,0,0,1)) return false;
        if (m_bot->HasAura(form)) { return false; }
    }

    if (ai->GetForm() == FORM_TREE) m_bot->RemoveAurasDueToSpell(TREE_OF_LIFE_FORM);
    else if (ai->GetForm() == FORM_CAT) m_bot->RemoveAurasDueToSpell(CAT_FORM);
    else if (ai->GetForm() == FORM_MOONKIN) m_bot->RemoveAurasDueToSpell(MOONKIN_FORM);
    else if (ai->GetForm() == FORM_DIREBEAR || ai->GetForm() == FORM_BEAR) m_bot->RemoveAurasDueToSpell(BEAR_FORM);
    else if (ai->GetForm() == FORM_TRAVEL) m_bot->RemoveAurasDueToSpell(TRAVEL_FORM);
    else if (ai->GetForm() == FORM_FLIGHT || ai->GetForm() == FORM_FLIGHT_EPIC)    m_bot->RemoveAurasDueToSpell(FLIGHT_FORM);
    else if (ai->GetForm() == FORM_AQUA) m_bot->RemoveAurasDueToSpell(AQUATIC_FORM);

    if (form == 1) { return true; }

    return CastSpell(form,m_bot,false);
}
bool PlayerbotPaladinAI::HealTarget(Unit *target, uint8 hp)
{
    if(!target || target->isDead()) return false;
    Player *m_bot = GetPlayerBot();

    if(hp < 10 && m_bot->isInCombat() && CastSpell(LOH, target)) { return true; }
    if(hp < 10 && m_bot->isInCombat() && CastSpell(SACRED_SHIELD,target)) { return true; }
    if(hp < 15 && m_bot->isInCombat() && CastSpell(HOP,target)) { return true; }
    if(hp < 20 && m_bot->isInCombat() && CastSpell(BEACON_OF_LIGHT,target)) { return true; }
    if(hp < 30 && CastSpell(HOLY_SHOCK,target,true,true,true)) { return true; }
    if(hp < 30 && m_bot->isInCombat() && CanCast(DIVINE_FAVOR,m_bot,true) && CanCast(HOLY_LIGHT,target,true) ) { CastSpell(DIVINE_FAVOR, m_bot,false); return CastSpell(HOLY_LIGHT,target,false); } //No gcd
    if(hp < 30 && CastSpell(FLASH_OF_LIGHT,target,true,true)) { return true; }
    if(hp < 40 && m_bot->getRace() == (uint8) RACE_DRAENEI && CastSpell(R_GIFT_OF_NAARU,target)) { return true; } // no GCD but has cast
    if(hp < 65 && CastSpell(HOLY_LIGHT,target,true,true)) { return true; }
    if(hp < 85 && CastSpell(FLASH_OF_LIGHT,target,true,true)) { return true; }
    if(hp < 95 && m_bot->isInCombat() && CastSpell(BEACON_OF_LIGHT,target)) { return true; }

    return false;
} //end HealTarget
bool PlayerbotShamanAI::ChangeTotems(uint32 mode)
{
    uint32 earth=0, fire=0, water=0, air=0;

    PlayerbotAI *ai = GetAI();
    if(!ai) return false;
    Player *m_bot = GetPlayerBot();
    if(!m_bot || m_bot->isDead()) return false;

    Unit *pTarget = m_bot->GetSelectedUnit();
    Unit *pVictim = NULL;
    if (m_bot->GetSelectedUnit()->IsFriendlyTo(m_bot)) pTarget = NULL;
    if (pTarget) pVictim = pTarget->getVictim();

    //Defaults
    if (!HasAuraName(m_bot,"Horn of Winter") )earth = STRENGTH_OF_EARTH_TOTEM;
    if (!earth) earth = STONESKIN_TOTEM;
    if (!earth) earth = EARTHBIND_TOTEM;
    fire = TOTEM_OF_WRATH;
    if (!fire) fire = FLAMETONGUE_TOTEM;
    if (!fire) fire = SEARING_TOTEM;
    water = MANA_SPRING_TOTEM;
    if (!water) water = HEALING_STREAM_TOTEM;
    if (TALENT_ELEMENTAL || TALENT_RESTO) air = WRATH_OF_AIR_TOTEM;
    else air = WINDFURY_TOTEM;

    //Target reactive stuff
    if (pTarget)
    {
        if (GROUNDING_TOTEM && pTarget->IsNonMeleeSpellCasted(true)) air = GROUNDING_TOTEM;
    }

    if (STONESKIN_TOTEM && isUnderAttack()) earth = STONESKIN_TOTEM;

    uint32 totz[4] = {earth, fire, water, air};

    for (int i = 0; i < 4; i++)
    {
        if (!totz[i]) continue;
        SpellInfo const *tSpell = GetSpellInfo(totz[i]);
        SpellEntry *tmp = 0;
        tmp->Id = tSpell->Id;
        if (!tSpell) continue;
        uint32 tEntry = (uint32) tSpell->Effects->MiscValue;
        if (!tEntry) continue;
        //CreatureTemplate const *totemEntry = ObjectMgr::GetCreatureTemplateStore(tEntry);
        if (!tEntry) continue;

        if (CanCast(totz[i], m_bot) && !m_bot->FindNearestCreature(tEntry,30)) {
            return CastSpell(totz[i],m_bot,false);
        }
    }
    return false;
}
bool PlayerbotPaladinAI::RezTarget (Unit *target)
{
    if(!target || target->isAlive()) return false;
    Player *m_bot = GetPlayerBot();
    if (target->IsNonMeleeSpellCasted(true)) { return false; } //Already resurrected
    if (m_bot->isInCombat()) { return false; }

    if (!CanCast(REDEMPTION,target)) return false;
    std::string msg = "Rezzing ";
    msg += target->GetName();
    GetPlayerBot()->Say(msg, LANGUAGE_UNIVERSAL);
    return CastSpell(REDEMPTION, target, false);
}
bool PlayerbotPaladinAI::ChangeAura(uint32 aura)
{
    Player *m_bot = GetPlayerBot();
    if(!aura) return false;

    if(!CanCast(aura,m_bot)) return false;

    if(m_bot->HasAura(aura))
    {
        if (aura == DEVOTION_AURA)
        {
            if (ChangeAura(FIRE_AURA)) return true;
            if (ChangeAura(FROST_AURA)) return true;
            if (ChangeAura(SHADOW_AURA)) return true;
            return true;
        }
        else return ChangeAura(DEVOTION_AURA);
    }
    return CastSpell(aura,m_bot,false);
}
Beispiel #12
0
_THyPhyReturnObject* _THyPhy::CastResult (const void* theObject, const int requestedType)
{
    _THyPhyReturnObject * convertedObject = nil;
    if (CanCast(theObject,requestedType)) {
        int hyphyObjClass = ((_PMathObj)theObject)->ObjectClass();
        switch (hyphyObjClass) {
        case NUMBER: {
            if (hyphyObjClass == NUMBER) {
                return new _THyPhyNumber (((_PMathObj)theObject)->Compute()->Value());
            }
            if (hyphyObjClass == STRING) {
                _String sV ((_String*)((_FString*)theObject)->toStr());
                return new _THyPhyNumber (sV.toNum());
            }
        }
        case STRING: {
            _String sV ((_String*)((_PMathObj)theObject)->toStr());
            return new _THyPhyString (sV.sData,sV.sLength);
        }
        case MATRIX: {
            if (hyphyObjClass == NUMBER) {
                double evaluate = ((_PMathObj)theObject)->Compute()->Value();
                return new _THyPhyMatrix (1,1,&evaluate);
            }

            if (hyphyObjClass == MATRIX) {
                _Matrix * evalutedNumeric =  (_Matrix*)((_Matrix*)(((_PMathObj)theObject)->Compute()))
                                             ->ComputeNumeric();

                return new _THyPhyMatrix (evalutedNumeric->GetHDim(),evalutedNumeric->GetVDim(),evalutedNumeric->theData);
            }
        }
        }
    }

    return convertedObject;
}
    void DoNonCombatActions()
    {
        Feast();

        if(isTimerReady(GC_Timer) && !m_creature->HasAura(SPELL_LIGHTNING_SHIELD, 0))
            doCast(m_creature, SPELL_LIGHTNING_SHIELD);

        //Casts buffs
       // if(!m_creature->isInCombat())
       // {
            //if(!m_creature->HasAura(SPELL_WINDFURY_WEAPON, 0)) doCast(m_creature, SPELL_WINDFURY_WEAPON);
 //           if(isTimerReady(GC_Timer) && !m_creature->HasAura(SPELL_LIGHTNING_SHIELD, 0))
   //             doCast(m_creature, SPELL_LIGHTNING_SHIELD);
       // }


        //Heal/rez others
        //
        //check group members, this doesn't check bots/pets.  They will be done later.  Preference
        //goes to real players first.
        //
        //buff and heal group
        if(master->GetGroup())
        {
            RezGroup(SPELL_SHAMAN_REZZ, master);
            BuffAndHealGroup(master);
           // CureGroup(master);
        }


        /* TESTING */
        Group::MemberSlotList const &a =((Player*)master)->GetGroup()->GetMemberSlots();
        for(Group::member_citerator itr = a.begin(); itr != a.end(); itr++)
        {
            Player *tPlayer = ((Player *)master)->GetObjPlayer(itr->guid);
            if(tPlayer == NULL) continue;
            //healing others
            if(tPlayer->isAlive() &&
            isTimerReady(Others_Heal_Timer) &&
            tPlayer->GetGUID() != master->GetGUID() &&
            tPlayer->GetHealth()*100 / tPlayer->GetMaxHealth() < 75 &&
            CanCast(tPlayer, GetSpellStore()->LookupEntry (SPELL_CHAIN_HEAL)))
            {
                doCast(tPlayer, SPELL_CHAIN_HEAL, false);
                Others_Heal_Timer = 100;
            }

            //rezzes
            if(tPlayer->isDead() &&
            !m_creature->isInCombat() &&
            //CanCast(tPlayer, GetSpellStore()->LookupEntry (SPELL_SHAMAN_REZZ)) &&
            m_creature->GetDistance(tPlayer) < 40 &&
            isTimerReady(Rez_Timer))
            {
                char *str = (char *)malloc(32);
                sprintf(str, "Rezzing %s", tPlayer->GetName());
                m_creature->MonsterSay(str, LANG_UNIVERSAL, NULL);
                free(str);
                doCast(tPlayer, SPELL_SHAMAN_REZZ, false);
                Rez_Timer = 160;
            }
        }
        /* TESTING */



/* TESTING */
        if((master->GetHealth()*100 / master->GetMaxHealth() < 90) && Lesser_Healing_Timer <= 0)
        {
            doCast(master, SPELL_LESSER_HEALING);
            Lesser_Healing_Timer = 90;
            Heal_Timer = Heal_Timer + 5; //wait 5 seconds before casting a real heal
            //if(master->isInCombat()) && master->getVictim() == NULL) return;
            return;
        } else if(Lesser_Healing_Timer >= 0) --Lesser_Healing_Timer;

        if((master->GetHealth()*100 / master->GetMaxHealth() < 75) && isTimerReady(Heal_Timer))
        {
            doCast(master, SPELL_CHAIN_HEAL);
            Heal_Timer = 10;
        }

        if(m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 90)
        {
            if(Self_Lesser_Healing_Timer <= 0)
            {
                doCast(m_creature, SPELL_LESSER_HEALING);
                Self_Lesser_Healing_Timer = 90;
                return;
            } else if(Self_Lesser_Healing_Timer >= 0)
                --Self_Lesser_Healing_Timer;
        }
/* TESTING */
        }
void PlayerbotHunterAI::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);

    Pet *pet = m_bot->GetPet();
    if (m_tank->GetGUID() == m_bot->GetGUID() && pet && pet->isAlive() && pet->isInCombat()) { m_tank = pet; }
    uint8 petThreat = 0;
    if (pet) { GetThreatPercent(pTarget,pet); }

 //   switch (ai->GetScenarioType())
//    {
//        case PlayerbotAI::SCENARIO_DUEL:
 //           ai->CastSpell(RAPTOR_STRIKE);
 //           return;
//    }

    // ------- Non Duel combat ----------


    #pragma region Choose Target
    // Choose Target
    if (isUnderAttack()) // I am under attack
    {
        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

    #pragma region Pet Actions
    // Pet's own Actions
    if( pet && pet->isAlive() )
    {
        // Setup pet
        if (pet->GetCharmInfo()->IsAtStay()) {pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); }

        //Heal pet
        if ( ( ((float)pet->GetHealth()/(float)pet->GetMaxHealth()) < 0.5f )
        && ( PET_MEND>0 && !pet->getDeathState() != ALIVE && pVictim != m_bot
        && CastSpell(PET_MEND,m_bot) )) { return; }

        // Set pet to attack hunter's attacker > its own attackers > hunter's target
        if (!pet->getVictim()) { pet->AI()->AttackStart(pTarget); }
        else if (isUnderAttack(m_bot)) { pet->AI()->AttackStart(pTarget); }  //Always help hunter if she's under attack
        else if (pet->getVictim()->GetGUID() != pTarget->GetGUID() && !isUnderAttack(pet)) { pet->AI()->AttackStart(pTarget); }
        else if (isUnderAttack(pet)) // Pet is under attack and hunter has no attackers
        {
            if ( pet->getVictim()->getVictim() && pet->getVictim()->getVictim()->GetGUID() == pet->GetGUID() && pDist <= 2) {  } // My target is almost up to me, no need to search
            else //Have to select nearest target
            {
                Unit *curAtt = GetNearestAttackerOf(pet,true);
                if (curAtt && (!pet->getVictim() || curAtt->GetGUID() != pet->getVictim()->GetGUID()))
                {
                    pet->AI()->AttackStart(curAtt); //Attack nearest attacker
                }
            }
            //Actions to do under attack (Always tank it, and try to kill it, until someone (!= hunter) takes aggro back)
            //Hunter should help her pet whether main tank or not, unless she's being attacked (BEWARE Targeting Loop possibility)
            if (pet->getVictim() && !isUnderAttack(m_bot) && pet->getVictim()->GetGUID() != pTarget->GetGUID())
            {
                m_bot->SetSelection(pet->getVictim()->GetGUID());
                DoNextCombatManeuver(pet->getVictim()); //Restart new update to get variables fixed..
                return;
            }

        }
        // Pet tanking behaviour
        if (pet->GetGUID() == m_tank->GetGUID() || isUnderAttack(m_bot) || isUnderAttack(pet))
        {
            if (GROWL) pet->GetCharmInfo()->SetSpellAutocast(GROWL,true); //Autocast growl
            if (BAD_ATTITUDE) pet->GetCharmInfo()->SetSpellAutocast(BAD_ATTITUDE,true);
            if (COWER) pet->GetCharmInfo()->SetSpellAutocast(COWER,false);
            if (CastSpell(INTIMIDATION,m_bot)) { return; }
        }
        else
        {
            if (GROWL) pet->GetCharmInfo()->SetSpellAutocast(GROWL,false); //Do not try to get aggro
            if (BAD_ATTITUDE) pet->GetCharmInfo()->SetSpellAutocast(BAD_ATTITUDE,false);
            if (COWER) pet->GetCharmInfo()->SetSpellAutocast(COWER,true); //Autocast cower
        }
        // NORMAL PET dps attacks
        if (petThreat < threatThreshold || pet->GetGUID() == m_tank->GetGUID() || isUnderAttack(m_bot))
        {
            if (CastSpell(KILL_COMMAND,m_bot)) { }
            else if (CastSpell(BESTIAL_WRATH,m_bot)) { }
        }
        // NETHERSHOCK DEMORALIZINGSCREECH
    }
    #pragma endregion

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

    // Cast CC breakers if any match found  (does not work yet)
    // uint32 ccSpells[4] = { R_ESCAPE_ARTIST, R_EVERY_MAN_FOR_HIMSELF, R_WILL_OF_FORSAKEN, R_STONEFORM };
    // if (castSelfCCBreakers(ccSpells)) { } //most of them dont have gcd

    #pragma region Evasive manuevers
    // Do evasive manuevers if under attack
    if (isUnderAttack())
    {
        if (m_tank->GetGUID() == m_bot->GetGUID()) { } // i am tank and my pet is probably dead, so i have to face the attackers
        else if (CastSpell(FEIGN_DEATH,m_bot)) { return; } //avoid attack
        //else if (m_bot->getRace() == (uint8) RACE_NIGHTELF && CastSpell(R_SHADOWMELD,m_bot) ) { return; }
        else if (CastSpell(CONCUSSIVE_SHOT,pTarget)) { return; }
        else if (CastSpell(WYVERN_STING,pTarget)) { return; }
        else if (CastSpell(SCATTER_SHOT,pTarget)) { return; }
        else if (CastSpell(FREEZING_ARROW,pTarget)) { return; }
        else if (CastSpell(MISDIRECTION,m_tank)) { return; }
        else if (m_bot->getRace() == (uint8) RACE_TAUREN && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget) ) { return; } //no gcd but is cast
        else if (pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_BEAST && CastSpell(SCARE_BEAST,pTarget)) { return; }
        else if (pDist <= 2 && CastSpell(FREEZING_TRAP,pTarget)) { return; }
    }
    #pragma endregion

    //Select combat mode
    m_role = BOT_ROLE_DPS_RANGED;
    if ((isUnderAttack()  && pDist <= ATTACK_DISTANCE) || !m_bot->GetUInt32Value(PLAYER_AMMO_ID) ) { m_role = BOT_ROLE_DPS_MELEE; }

    TakePosition(pTarget);

    #pragma region Buff / Protect
    //Buff 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(TRUESHOT_AURA, m_bot)) { return; }
    if (CastSpell(RAPID_FIRE,m_bot)) { return; }
    if (CastSpell(HUNTERS_MARK,pTarget)) { return; }
    if ((ai->GetHealthPercent() < 80 || ai->GetManaPercent() < 60 ) && CastSpell(READINESS,m_bot)) { } //no gcd


    //Protect yourself if needed
    if (m_bot->getRace() == (uint8) RACE_DWARF && ai->GetHealthPercent() < 75 && CastSpell(R_STONEFORM,m_bot) ) { } //no gcd
    if (ai->GetHealthPercent() < 20 && CastSpell(DETERRENCE,m_bot)) {} //No GCD
    if (m_bot->getRace() == (uint8) RACE_DRAENEI && ai->GetHealthPercent() < 55 && CastSpell(R_GIFT_OF_NAARU,m_bot)) { return;  }

    //Break Spells
    if (m_bot->getRace() == (uint8) RACE_BLOODELF && pDist < 8 && ( pTarget->IsNonMeleeSpellCasted(true) || ai->GetManaPercent() < 20 ) && CastSpell(R_ARCANE_TORRENT, pTarget) ) { } //no gcd
    if (pTarget->IsNonMeleeSpellCasted(true) && CastSpell(SILENCING_SHOT, pTarget) ) { return; }
    if (pTarget->IsNonMeleeSpellCasted(true) && CastSpell(SCATTER_SHOT, pTarget) ) { return; }

    //Catch
    if (pTarget->HasUnitMovementFlag(UNIT_FLAG_FLEEING))
    {
        if (CastSpell(WING_CLIP,pTarget)) return;
        if (CastSpell(CONCUSSIVE_SHOT,pTarget)) return;
        if (CastSpell(SCATTER_SHOT, pTarget) ) { return; }
    }
    #pragma endregion

    //Do combat
    switch (m_role)
    {
        #pragma region BOT_ROLE_DPS_MELEE
        case BOT_ROLE_DPS_MELEE:
            if (AUTO_SHOT) { m_bot->InterruptNonMeleeSpells( true, AUTO_SHOT ); } //Stop autoshot
            if (CastSpell(ASPECT_OF_THE_MONKEY,m_bot)) { return; } //Get Monkey aspect

            if (m_bot->getRace() == (uint8) RACE_TAUREN && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return; } //no gcd but is cast

            // Threat control
            if (pThreat < threatThreshold || m_tank->GetGUID() == m_bot->GetGUID() || m_bot->HasAura(MISDIRECTION) ) { } //Continue attack
            else
            {
                if (pet && isUnderAttack(pet) && pet->getVictim() && pet->getVictim()->GetGUID() != pTarget->GetGUID()) //Should be helping pet
                {
                    m_bot->SetSelection(pet->getVictim()->GetGUID());
                    return;
                }
                else 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(FEIGN_DEATH,m_bot)) { return; }
                else { return; } // No more threat reducing spells, just slow down
            }

            if (CastSpell(RAPTOR_STRIKE,pTarget,true,true)) {} //No gcd
            if (CastSpell(MONGOOSE_BITE,pTarget,true,true)) { return; } // Cannot be sure if casted or not
            else if (CastSpell(COUNTERATTACK,pTarget,true,true)) { return; } // Cannot be sure if casted or not
            if (CastSpell(WING_CLIP,pTarget)) { return; }
            if (isUnderAttack(m_tank,6) && CastSpell(SNAKE_TRAP,m_bot)) { return; }
            if (isUnderAttack(m_tank,4) && CastSpell(EXPLOSIVE_TRAP,m_bot)) { return; }
            if (CastSpell(IMMOLATION_TRAP,m_bot)) { return; }
            break;
        #pragma endregion

        #pragma region BOT_ROLE_DPS_RANGED
        case BOT_ROLE_DPS_RANGED:
            if (m_pulling) {
                if (GetAI()->CastSpell(CONCUSSIVE_SHOT,pTarget) ||
                    GetAI()->CastSpell(AUTO_SHOT,pTarget)) {
                    m_pulling = false;
                    GetAI()->SetCombatOrder(ORDERS_NONE);
                    GetAI()->Follow(*GetMaster());
                    GetAI()->SetIgnoreUpdateTime(2);

                    if(HasPet(GetPlayerBot()))
                        m_bot->GetPet()->SetReactState(REACT_DEFENSIVE);
                }
                return;
            }
            if (AUTO_SHOT && !m_bot->FindCurrentSpellBySpellId(AUTO_SHOT)) { ai->CastSpell(AUTO_SHOT,pTarget); } //Start autoshot
            if (!(ai->GetManaPercent() < 85 && m_bot->HasAura(ASPECT_OF_THE_VIPER)) && CastSpell(ASPECT_OF_THE_HAWK,m_bot)) { return; } //Get Hawk aspect
            if ((ai->GetManaPercent() < 25) && CastSpell(ASPECT_OF_THE_VIPER,m_bot,true,false,true)) { return; } //Build up mana

            // if i am main tank, protect master by taunt
            if(m_tank->GetGUID() == m_bot->GetGUID())
            {
                // Taunt if needed (Only for master)
                Unit *curAtt = GetAttackerOf(GetMaster());
                if (curAtt && CastSpell(DISTRACTING_SHOT, curAtt))  { return; }
                // My target is not attacking me, taunt..
                if (pVictim && pVictim->GetGUID() != m_bot->GetGUID() && CastSpell(DISTRACTING_SHOT, pTarget) )  { return; }
            }
            // If i am not tank, transfer threat to tank or pet..
            else
            {
                if (CastSpell(MISDIRECTION,m_tank)) { return; }
                if (pet && pet->isAlive() && CastSpell(MISDIRECTION,pet)) { return; }

                // Threat control
                if (pThreat < threatThreshold || m_bot->HasAura(MISDIRECTION) ) { } //Continue attack
                else
                {
                    if (pet && isUnderAttack(pet) && pet->getVictim() && pet->getVictim()->GetGUID() != pTarget->GetGUID()) //Should be helping pet
                    {
                        m_bot->SetSelection(pet->getVictim()->GetGUID());
                        return;
                    }
                    else 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(FEIGN_DEATH,m_bot)) { return; }
                    else { return; } // No more threat reducing spells, just slow down
                }
            }

            // DO dps
            if (ai->GetHealthPercent(*pTarget) < 20 && CastSpell(KILL_SHOT,pTarget)) { return; }
            if (isUnderAttack(m_tank,4) && CastSpell(MULTI_SHOT,pTarget)) { return; }
            if (isUnderAttack(m_tank,4) && CastSpell(VOLLEY,pTarget)) { GetAI()->SetIgnoreUpdateTime(7); return; }
            if (CanCast(CHIMERA_SHOT,pTarget) &&
                (pTarget->HasAura(VIPER_STING,m_bot->GetGUID()) || pTarget->HasAura(SERPENT_STING,m_bot->GetGUID()) )
                && CastSpell(CHIMERA_SHOT,pTarget,false) ) { return; }
            if (ai->GetManaPercent() < 60 && ai->GetManaPercent(*pTarget) > 4 && CastSpell(VIPER_STING,pTarget)) { return; }
            if (!pTarget->HasAura(VIPER_STING,m_bot->GetGUID()) && CastSpell(SERPENT_STING,pTarget)) { return; }
            if (CastSpell(ARCANE_SHOT,pTarget)) { return; }
            if (CastSpell(BLACK_ARROW,pTarget)) { return; }
            if (CastSpell(EXPLOSIVE_SHOT,pTarget)) { return; }
            if (CastSpell(STEADY_SHOT,pTarget)) { return; }
            break;
        #pragma endregion
    }

    /*// drink potion if support / healer (Other builds simply overuse mana and waste mana pots)
    if(ai->GetManaPercent() < 5 && (m_role == BOT_ROLE_SUPPORT || m_role == BOT_ROLE_HEALER) )
    {
        Item *pItem = ai->FindPotion();
        if(pItem != NULL)
        {
            if (pItem->GetSpell() && m_bot->HasSpellCooldown(pItem->GetSpell()) ) { return; } //pot is in cooldown
            ai->UseItem(*pItem);
        }
    }*/
} // end DoNextCombatManeuver
void PlayerbotPaladinAI::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);

    uint8 reqHeal = 0;
    uint8 OwnPartyHP = GetHealthPercentRaid(m_bot, reqHeal);


    // Fill mana if needed
    if (m_bot->getRace() == (uint8) RACE_BLOODELF && pDist < 8 && ai->GetManaPercent() < 20 && CastSpell(R_ARCANE_TORRENT, pTarget)) { } //no gcd
    if (ai->GetManaPercent() < 30 && CastSpell (DIVINE_PLEA, m_bot)) { return; }

    // If hp is too low divine shield
    if (ai->GetHealthPercent() < 20 && (!m_bot->HasAura(DIVINE_SHIELD) || !m_bot->HasAura(HOP) || !m_bot->HasAura(SACRED_SHIELD)))
    {
        if (!m_bot->HasAura(FORBEARANCE))
        {
            if (CastSpell(DIVINE_SHIELD,m_bot)) { return; }
            if (CastSpell(HOP,m_bot)) { return; }
        }
        else if (CastSpell(SACRED_SHIELD,m_bot)) { return; }
    }

    // if i am under attack and if i am not tank or offtank: change target if needed
    if (m_tank->GetGUID() != m_bot->GetGUID() && !TALENT_PROT && isUnderAttack() )
    {
        // Keep hitting but reduce threat
        if (CastSpell(HOS,m_bot,true,true)) { }
        //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 region Choose Actions
    // Choose actions accoring to talents
    if (m_tank->GetGUID() == m_bot->GetGUID()) // Hey! I am Main Tank
    {
        if (TALENT_PROT) { m_role=BOT_ROLE_TANK; } //Just Keep Tanking
        else
        {
            if (TALENT_RETRI) {
                if ((ai->GetHealthPercent() <= 40 || masterHP <40 ) && (ai->GetManaPercent() >= 40)) { m_role = BOT_ROLE_SUPPORT; }
                else if (OwnPartyHP < 40 && ai->GetManaPercent() >= 30) { m_role = BOT_ROLE_SUPPORT; }
                else { m_role = BOT_ROLE_TANK; } //have no shield but can tank if you think so
            }
            else if (TALENT_HOLY) //I am both healer and tank?? Hmm
            {
                if ((ai->GetHealthPercent() <= 70 || masterHP <70 ) && (ai->GetManaPercent() >= 50))m_role = BOT_ROLE_SUPPORT;
                else if (OwnPartyHP < 20 && ai->GetManaPercent() >= 30) { m_role = BOT_ROLE_SUPPORT; }
                else m_role = BOT_ROLE_TANK;
            }
            else { m_role = BOT_ROLE_TANK; } //Unknown build or low level
        }
    }
    else if (TALENT_RETRI) {
        if ((ai->GetHealthPercent() <= 40 || masterHP <40 ) && (ai->GetManaPercent() >= 40)) { m_role = BOT_ROLE_SUPPORT; }
        else if (OwnPartyHP < 40 && ai->GetManaPercent() >= 30) {m_role = BOT_ROLE_SUPPORT;}
        else { m_role = BOT_ROLE_DPS_MELEE; }
    }
    else if (TALENT_PROT) {
        if ((ai->GetHealthPercent() <= 30 || masterHP <40 ) && (ai->GetManaPercent() >= 20)) { m_role = BOT_ROLE_SUPPORT; }
        else if (OwnPartyHP < 40 && ai->GetManaPercent() >= 40) { m_role = BOT_ROLE_SUPPORT; }
        else { m_role = BOT_ROLE_OFFTANK; }
    }
    else if (TALENT_HOLY) { m_role = BOT_ROLE_SUPPORT; }
    else { m_role = BOT_ROLE_DPS_MELEE; } //Unknown build or low level.. Mainly attack

	//takepos
    if (m_role == BOT_ROLE_SUPPORT || m_role == BOT_ROLE_HEALER) TakePosition(pTarget,BOT_ROLE_DPS_MELEE,0.5f);
    else TakePosition(pTarget,m_role);

    // If there's a cast stop
    if(m_bot->HasUnitState(UNIT_STATE_CASTING)) return;

    Unit *target = DoSelectLowestHpFriendly(40, 1000);
    switch(m_role)
    {
        #pragma region BOT_ROLE_SUPPORT
        case BOT_ROLE_SUPPORT:

            ChangeAura(CONCENTRATION_AURA);
            if (!TALENT_PROT && m_tank->GetGUID() != m_bot->GetGUID()) m_bot->RemoveAurasDueToSpell(RIGHTEOUS_FURY);
            // Choose Seal
            if (SOW && ai->GetManaPercent() <= 30) {    if (CastSpell(SOW,m_bot)) { return; } }
            else if (m_bot->HasAura(SOW) && ai->GetManaPercent() < 85) { } // Paladin was striving for mana, keep until he got most of his mana back
            else if(SOL && ai->GetHealthPercent() < 40) { if(CastSpell(SOL,m_bot)) { return; } }
            else if(CastSpell(SOR, m_bot)) { return; }

            if (!m_bot->HasAura(FORBEARANCE) && CastSpell(AVENGING_WRATH,m_bot)) { } // no gcd

            if (DoSupportRaid(m_bot)) { return; }
            //heal pets and bots
            if(target && target->isAlive() && HealTarget(target, target->GetHealth()*100 / target->GetMaxHealth()) ) { return; }

            if (ai->GetManaPercent() <= 80 && CastSpell(JOW,pTarget,true,true)) { return; }

            // Use Spells only if mana is sufficient..
            if(ai->GetManaPercent() < offensiveSpellThreshold ) return;

        break;
        #pragma endregion

        #pragma region BOT_ROLE_TANK / BOT_ROLE_OFFTANK
        case BOT_ROLE_TANK:
        case BOT_ROLE_OFFTANK:

            ChangeAura(DEVOTION_AURA);
            if (CastSpell(RIGHTEOUS_FURY,m_bot)) { return; }
            // Choose Seal
            if (SOW && ai->GetManaPercent() <= 30) { if (CastSpell(SOW,m_bot)) { return; } }
            else if (m_bot->HasAura(SOW) && ai->GetManaPercent() < 85) { } // Paladin was striving for mana, keep until he got most of his mana back
            else if (SOL && ai->GetHealthPercent() < 40) { if (CastSpell(SOL,m_bot)) { return; } }
            else if (CastSpell(SOR,m_bot)) { return; }

            // We are tank/offtank threat is not an issiue;
            // Use taunts only if helping target is not main tank..
            // Taunt if needed (Only for master)
            if(GetMaster()->GetGUID() != m_tank->GetGUID())
            {
                // Taunt if needed (Only for master)
                Unit *curAtt = GetAttackerOf(GetMaster());
                if (curAtt)
                {
                    if (isUnderAttack(GetMaster(),2) && CastSpell(RIGHTEOUS_DEFENSE, GetMaster())) { return; }
                    if (CastSpell(HOR, curAtt,true,true))  { } //No GCD
                }
            }
            // My target is not attacking me, taunt..
            if ( m_tank->GetGUID() == m_bot->GetGUID() && pVictim && pVictim->GetGUID() != m_bot->GetGUID() && CastSpell(HOR, pTarget,true,true) )  { } //NO GCD

            // Tank specials
            if (TALENT_PROT && ai->GetManaPercent() < 90 && CastSpell (DIVINE_PLEA, m_bot)) { return; } //Prot paladin always uses this..
            if (pVictim && pVictim->GetGUID() == m_bot->GetGUID() && CastSpell(HOLY_SHIELD,m_bot)) { return; }
            if (CastSpell(AVENGERS_SHIELD,pTarget,true,true)) { return; }
            if (CastSpell(HOTR,pTarget,true,true)) { return; }
            if (CastSpell(HOLY_WRATH,pTarget,true,true)){ return; }
            if (CastSpell(CONSECRATION,pTarget)) { return; }
            if (m_bot->getRace() == (uint8) RACE_DWARF && CastSpell(R_STONEFORM,m_bot)) { return; }

            if (DoSupportRaid(m_bot)) { return; }
            //heal pets and bots
            if(target && target->isAlive() && HealTarget(target, target->GetHealth()*100 / target->GetMaxHealth()) ) { return; }


        break;
		#pragma endregion

		#pragma region BOT_ROLE_DPS_MELEE
		case BOT_ROLE_DPS_MELEE:

			ChangeAura(RETRIBUTION_AURA);
			if (!TALENT_PROT && m_tank->GetGUID() != m_bot->GetGUID()) m_bot->RemoveAurasDueToSpell(RIGHTEOUS_FURY);
			if (CastSpell(SOV,m_bot)) { return; }

			if (CastSpell (HAMMER_OF_JUSTICE, pTarget)) { return; }
			if (!m_bot->HasAura(FORBEARANCE) && CastSpell(AVENGING_WRATH,m_bot)) {} //no gcd
			if (CastSpell(JOW,pTarget)) { return; }
			if (CastSpell(DIVINE_STORM, pTarget)) { return; }
			if (CastSpell(CRUSADER_STRIKE, pTarget)) { return; }
			if (GetAI()->GetHealthPercent(*pTarget)<20 && CastSpell(HAMMER_OF_WRATH, pTarget)) { return; }
			if (CastSpell(CONSECRATION,pTarget)) { return; }
			if (m_bot->HasAura(AOW) && CastSpell(EXORCISM,pTarget)) { return; }
			if (CastSpell(HOLY_WRATH,pTarget)) { return; }

		break;
        #pragma endregion

    }
    #pragma region PaladinCommon
    // Shared dps spells
    if (pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_HUMANOID && pTarget->IsNonMeleeSpellCasted(true) && CastSpell (REPENTANCE, pTarget)) { return; }
    if (m_bot->getRace() == (uint8) RACE_BLOODELF && pDist < 8 && pTarget->IsNonMeleeSpellCasted(true) && CastSpell(R_ARCANE_TORRENT, pTarget)) { } //no gcd
    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 at threat limit, stop
    if(pThreat > threatThreshold && !TALENT_PROT && 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(HOS,m_bot)) { return; } //Lets see if we can manage with HOS
            else { return; } //use no spells and wait threat to be reduced
        }
    }
    // Continue attacking if theres excess mana (for healers)
    if (m_role == BOT_ROLE_SUPPORT && ai->GetManaPercent() < offensiveSpellThreshold) { return; }

    if (GetAI()->GetHealthPercent(*pTarget)<20 && CastSpell(HAMMER_OF_WRATH, pTarget,true,true)) { return; } //no gcd but cast
    if (CastSpell (HAMMER_OF_JUSTICE, pTarget)) { return; }
    if (CanCast(JOW,pTarget,true) &&
        ( ( ai->GetManaPercent() <= 70 && ai->GetHealthPercent() > 90)
        || ( ai->GetManaPercent() <= 50 && ai->GetHealthPercent() > 75)
        || ( ai->GetManaPercent() <= 20 && ai->GetHealthPercent() > 20) )
        && CastSpell(JOW,pTarget,false)) { return; }
    else if (CastSpell(JOL,pTarget),true,true) { return; }
    if (CastSpell(SHIELD_OF_RIGHTEOUSNESS,pTarget,true,true)) { return; }
    if (CastSpell (DIVINE_STORM, pTarget,true,true)) { return; }
    if (CastSpell (CRUSADER_STRIKE, pTarget,true,true)) { return; }
    if (m_bot->getRace() == (uint8) RACE_TAUREN && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return; } //no GCD but cast
    if (isUnderAttack(m_tank,4) && CastSpell(HOLY_WRATH,pTarget,true,true)) { return; }
    if (isUnderAttack(m_tank,4) && CastSpell(CONSECRATION,pTarget)) { return; }
    if (CastSpell(HOLY_SHOCK,pTarget,true,true)) { return; }
    if (m_role != BOT_ROLE_SUPPORT && ai->GetManaPercent() > 60 && OwnPartyHP < 65 && DoSupportRaid(m_bot)) { return; } //if there is spare time and mana, do healz and other stuff..
    else if (m_role != BOT_ROLE_SUPPORT && ai->GetManaPercent() > 30 && DoSupportRaid(m_bot,30,false,false,false,true,false)) { return; }
    if (CastSpell(EXORCISM,pTarget,true,true)) { return; }


    // drink potion if support / healer (Other builds simply overuse mana and waste mana pots)
    if(ai->GetManaPercent() < 5 && (m_role == BOT_ROLE_SUPPORT || m_role == BOT_ROLE_HEALER) )
    {
        Item *pItem = ai->FindPotion();
        if(pItem != NULL)
        {
            if (pItem->GetSpell() && m_bot->HasSpellCooldown(pItem->GetSpell()) ) { return; } //pot is in cooldown
            ai->UseItem(*pItem);
        }
    }
    #pragma endregion

} //end DoNextCombatManeuver
bool PlayerbotPaladinAI::BuffPlayer(Unit *target)
{
    if(!target || target->isDead()) return false;
    Player *m_bot = GetPlayerBot();

    // Check if target already has a blessing by me..
    if (HasAuraName(target,BOW,m_bot->GetGUID()) ||
    HasAuraName(target,BOK,m_bot->GetGUID()) ||
    HasAuraName(target,BOM,m_bot->GetGUID()) ||
    HasAuraName(target,BOS,m_bot->GetGUID()) ||
    HasAuraName(target,GBOW,m_bot->GetGUID()) ||
    HasAuraName(target,GBOK,m_bot->GetGUID()) ||
    HasAuraName(target,GBOM,m_bot->GetGUID()) ||
    HasAuraName(target,GBOS,m_bot->GetGUID())
    ) return false;

#pragma region Choose Buff > Class
    switch(target->getClass())
    {
        case CLASS_MAGE:
        case CLASS_WARLOCK:
            if (CanCast(GBOW,target) && !HasAuraName(target,BOW) && !HasAuraName(target,GBOW) ) return CastSpell(GBOW,target,false);
            else if (CanCast(GBOK,target) && !HasAuraName(target,BOK) && !HasAuraName(target,GBOK) ) return CastSpell(GBOK,target,false);
            else if (CanCast(GBOS,target) && !HasAuraName(target,BOS) && !HasAuraName(target,GBOS) ) return CastSpell(GBOS,target,false);
            break;
        case CLASS_PRIEST:
            if (CanCast(GBOK,target) && !HasAuraName(target,BOK) && !HasAuraName(target,GBOK) ) return CastSpell(GBOK,target,false);
            else if (CanCast(GBOW,target) && !HasAuraName(target,BOW) && !HasAuraName(target,GBOW) ) return CastSpell(GBOW,target,false);
            else if (CanCast(GBOS,target) && !HasAuraName(target,BOS) && !HasAuraName(target,GBOS) ) return CastSpell(GBOS,target,false);
            break;
        case CLASS_HUNTER:
            if (CanCast(GBOM,target) && !HasAuraName(target,BOM) && !HasAuraName(target,GBOM) ) return CastSpell(GBOM,target,false);
            else if (CanCast(GBOK,target) && !HasAuraName(target,BOK) && !HasAuraName(target,GBOK) ) return CastSpell(GBOK,target,false);
            else if (CanCast(GBOW,target) && !HasAuraName(target,BOW) && !HasAuraName(target,GBOW) ) return CastSpell(GBOW,target,false);
            else if (CanCast(GBOS,target) && !HasAuraName(target,BOS) && !HasAuraName(target,GBOS) ) return CastSpell(GBOS,target,false);
            break;
        case CLASS_ROGUE:
            if (CanCast(GBOM,target) && !HasAuraName(target,BOM) && !HasAuraName(target,GBOM) ) return CastSpell(GBOM,target,false);
            else if (CanCast(GBOK,target) && !HasAuraName(target,BOK) && !HasAuraName(target,GBOK) ) return CastSpell(GBOK,target,false);
            else if (CanCast(GBOS,target) && !HasAuraName(target,BOS) && !HasAuraName(target,GBOS) ) return CastSpell(GBOS,target,false);
            break;
        case CLASS_WARRIOR:
        case CLASS_DEATH_KNIGHT:
            if (target->GetUnitDodgeChance() + target->GetUnitParryChance() > 40)
            {
                if (CanCast(GBOS,target) && !HasAuraName(target,BOS) && !HasAuraName(target,GBOS) ) return CastSpell(GBOS,target,false);
                else if (CanCast(GBOK,target) && !HasAuraName(target,BOK) && !HasAuraName(target,GBOK) ) return CastSpell(GBOK,target,false);
                else if (CanCast(GBOM,target) && !HasAuraName(target,BOM) && !HasAuraName(target,GBOM) ) return CastSpell(GBOM,target,false);
            }
            else
            {
                if (CanCast(GBOK,target) && !HasAuraName(target,BOK) && !HasAuraName(target,GBOK) ) return CastSpell(GBOK,target,false);
                else if (CanCast(GBOM,target) && !HasAuraName(target,BOM) && !HasAuraName(target,GBOM) ) return CastSpell(GBOM,target,false);
                else if (CanCast(GBOS,target) && !HasAuraName(target,BOS) && !HasAuraName(target,GBOS) ) return CastSpell(GBOS,target,false);
            }
            break;
        case CLASS_DRUID:
        case CLASS_SHAMAN:
        case CLASS_PALADIN:
            if (target->GetMaxPower(target->getPowerType()) > target->GetMaxHealth())
            {
                if (CanCast(GBOW,target) && !HasAuraName(target,BOW) && !HasAuraName(target,GBOW) ) return CastSpell(GBOW,target,false);
                else if (CanCast(GBOK,target) && !HasAuraName(target,BOK) && !HasAuraName(target,GBOK) ) return CastSpell(GBOK,target,false);
                else if (CanCast(GBOS,target) && !HasAuraName(target,BOS) && !HasAuraName(target,GBOS) ) return CastSpell(GBOS,target,false);
                else if (CanCast(GBOM,target) && !HasAuraName(target,BOM) && !HasAuraName(target,GBOM) ) return CastSpell(GBOM,target,false);
            }
            else if (target->GetUnitDodgeChance() + target->GetUnitParryChance() > 40)
            {
                if (CanCast(GBOS,target) && !HasAuraName(target,BOS) && !HasAuraName(target,GBOS) ) return CastSpell(GBOS,target,false);
                else if (CanCast(GBOK,target) && !HasAuraName(target,BOK) && !HasAuraName(target,GBOK) ) return CastSpell(GBOK,target,false);
                else if (CanCast(GBOM,target) && !HasAuraName(target,BOM) && !HasAuraName(target,GBOM) ) return CastSpell(GBOM,target,false);
                else if (CanCast(GBOW,target) && !HasAuraName(target,BOW) && !HasAuraName(target,GBOW) ) return CastSpell(GBOW,target,false);
            }
            else
            {
                if (CanCast(GBOK,target) && !HasAuraName(target,BOK) && !HasAuraName(target,GBOK) ) return CastSpell(GBOK,target,false);
                else if (CanCast(GBOM,target) && !HasAuraName(target,BOM) && !HasAuraName(target,GBOM) ) return CastSpell(GBOM,target,false);
                else if (CanCast(GBOW,target) && !HasAuraName(target,BOW) && !HasAuraName(target,GBOW) ) return CastSpell(GBOW,target,false);
                else if (CanCast(GBOS,target) && !HasAuraName(target,BOS) && !HasAuraName(target,GBOS) ) return CastSpell(GBOS,target,false);
            }
            break;

        default:
                if (CanCast(GBOK,target) && !HasAuraName(target,BOK) && !HasAuraName(target,GBOK) ) return CastSpell(GBOK,target,false);
                else if (CanCast(GBOM,target) && !HasAuraName(target,BOM) && !HasAuraName(target,GBOM) ) return CastSpell(GBOM,target,false);
                else if (CanCast(GBOW,target) && !HasAuraName(target,BOW) && !HasAuraName(target,GBOW) ) return CastSpell(GBOW,target,false);
                else if (CanCast(GBOS,target) && !HasAuraName(target,BOS) && !HasAuraName(target,GBOS) ) return CastSpell(GBOS,target,false);
                break;
    }
#pragma endregion

    return false;
}
void PlayerbotShamanAI::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);

    uint8 reqHeal = 0;
    uint8 OwnPartyHP = GetHealthPercentRaid(m_bot, reqHeal);

    switch(ai->GetScenarioType())
    {
        case SCENARIO_DUEL:
            ((ai->GetHealthPercent() < 80 && CastSpell(LESSER_HEAL)) ||
            CastSpell(LIGHTNING_BOLT, pTarget));
            return;
    }

    // Cast CC breakers if any match found (include any dispels first)  does not work yet
    //uint32 ccSpells[4] = { R_ESCAPE_ARTIST, R_EVERY_MAN_FOR_HIMSELF, R_WILL_OF_FORSAKEN, R_STONEFORM };
    //if (ai->GetManaPercent() < 35) { ccSpells[0] = 0; ccSpells[1] = 0; } //We dont have any mana to waste...
    //if (castSelfCCBreakers(ccSpells)) {  } // Most of them don't trigger gcd


    #pragma region Choose Actions
    // Choose actions accoring to talents
    if (m_tank->GetGUID() == m_bot->GetGUID()) { m_role=BOT_ROLE_TANK; } // Hey! I am Main Tank
    else if (TALENT_ENHANCEMENT) { m_role = BOT_ROLE_DPS_MELEE; }
    else if (TALENT_ELEMENTAL) { m_role = BOT_ROLE_DPS_RANGED; }
    else if (TALENT_RESTO) { m_role = BOT_ROLE_SUPPORT; }
    else { m_role = BOT_ROLE_DPS_MELEE; } //Unknown build or low level.. Mainly attack

    // 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()  )
    {
            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

    // Choose Weapon Enchant
    if (ChangeWeaponEnchants()) return;

	if (TALENT_ELEMENTAL){ if (!m_bot->HasAura(WATER_SHIELD) && CastSpell(WATER_SHIELD,m_bot)) { return; }}
	if (TALENT_ENHANCEMENT){ if (!m_bot->HasAura(LIGHTNING_SHIELD) && CastSpell(LIGHTNING_SHIELD,m_bot)) { return; }}
	if (TALENT_RESTO){ if (!m_bot->HasAura(WATER_SHIELD) && CastSpell(WATER_SHIELD,m_bot)) { return; }}
    // Choose shield
	/*
    if (EARTH_SHIELD && ai->GetHealthPercent() < 80 && isUnderAttack()) { if (CastSpell(EARTH_SHIELD,m_bot)) { return; } }
    else if (WATER_SHIELD && ai->GetManaPercent() < 40) { if (CastSpell(WATER_SHIELD,m_bot)) { return; } }
    else if (LIGHTNING_SHIELD &&
        ( isUnderAttack() || m_tank->GetGUID() == m_bot->GetGUID() )  && !(m_bot->HasAura(WATER_SHIELD) && ai->GetManaPercent() < 80)
        ) { if (CastSpell(LIGHTNING_SHIELD,m_bot)) { return; } }
    else if (CastSpell(WATER_SHIELD,m_bot)) { return; }
	*/
    // If there's a cast stop
    if(m_bot->HasUnitState(UNIT_STAT_CASTING)) return;

    switch(m_role)
    {
        #pragma region BOT_ROLE_TANK / BOT_ROLE_OFFTANK
        case BOT_ROLE_TANK:
        case BOT_ROLE_OFFTANK:
             if (!TALENT_ELEMENTAL && !TALENT_RESTO) { TakePosition(pTarget); }
            else { TakePosition(pTarget,BOT_ROLE_DPS_RANGED); } // mob will come to you sooner or later no need to hurry

            // Do support stuff
            if (!m_bot->isMoving() && ChangeTotems(m_role)) { return; }
            if (ai->GetManaPercent() > 70 && DoSupportRaid(m_bot)) { return; }

            break;
        #pragma endregion

        #pragma region BOT_ROLE_DPS_MELEE
        case BOT_ROLE_DPS_MELEE:
            TakePosition(pTarget);
            // Do support stuff
            if (!m_bot->isMoving() && ChangeTotems(m_role)) { return; }
            if (ai->GetManaPercent() > 40 && DoSupportRaid(m_bot)) { return; }
            break;
        #pragma endregion

        #pragma region BOT_ROLE_DPS_RANGED
        case BOT_ROLE_DPS_RANGED:
            TakePosition(pTarget);
            // Do support stuff
            if (!m_bot->isMoving() && ChangeTotems(m_role)) { return; }
            if (ai->GetManaPercent() > 40 && DoSupportRaid(m_bot)) { return; }
            break;
        #pragma endregion

        #pragma region BOT_ROLE_SUPPORT
        case BOT_ROLE_SUPPORT:
            TakePosition(pTarget);
            // Do support stuff
            if (!m_bot->isMoving() && ChangeTotems(m_role)) { return; }
            if (DoSupportRaid(m_bot)) { return; }
            //heal pets and bots
            Unit *target = DoSelectLowestHpFriendly(40, 1000);
            if(target && target->isAlive() && HealTarget(target, target->GetHealth()*100 / target->GetMaxHealth()) ) { return; }

            break;
        #pragma endregion
    }
    #pragma region ShamanCommon


    //Defensive Stuff
    if (m_tank->GetGUID() != m_bot->GetGUID() && pVictim && pVictim->GetGUID() == m_bot->GetGUID() )
    {
        if (pDist > 5 && CastSpell(FROST_SHOCK, pTarget)) { return; }
        if ((pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_BEAST || pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_HUMANOID) && CastSpell(HEX, pTarget)) { return; } // no gcd
        if (CastSpell(WIND_SHEAR, pTarget)) { } // no gcd
    }
    if (m_bot->getRace() == (uint8) RACE_BLOODELF && pDist < 8 && pTarget->IsNonMeleeSpellCasted(true) && CastSpell(R_ARCANE_TORRENT, pTarget)) { } //no gcd
    if (pTarget->IsNonMeleeSpellCasted(true) && CastSpell(WIND_SHEAR, pTarget)) { } //no gcd
    if (m_bot->getRace() == (uint8) RACE_TAUREN && pVictim && pVictim->GetGUID() == m_bot->GetGUID() && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return; }

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


    //Buff and restores
    if ( ( (ai->GetHealthPercent() < 60 && isUnderAttack()) ||
        (ai->GetManaPercent() < 30) ) && CastSpell(SHAMANISTIC_RAGE, m_bot)) { return; }
    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 (!m_bot->HasAura(HEROISM) && !m_bot->HasAura(EXHAUSTION) && !m_bot->HasAura(SATED) && CastSpell(HEROISM,m_bot)) { return; }
    if (m_role != BOT_ROLE_SUPPORT && CastSpell(NATURES_SWIFTNESS, m_bot)) { } //healers keep it for healing no gcd
    else if (CastSpell(ELEMENTAL_MASTERY, m_bot)) { } //no gcd

    // If at threat limit, use WIND_SHEAR 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(WIND_SHEAR,pTarget)) { return; } //Lets see if we can manage
            else { return; } //use no spells and wait threat to be reduced
        }
    }


	if (TALENT_ELEMENTAL)
	{
		if (CastSpell(ELEMENTAL_MASTERY, m_bot)) { } //no gcd
		if (!pTarget->HasAura(FLAME_SHOCK,m_bot->GetGUID()) && CastSpell(FLAME_SHOCK,pTarget)) { return; }
		if (CastSpell(LAVA_BURST,pTarget)) { return; }
		if (CastSpell(CHAIN_LIGHTNING,pTarget)) { return; }
		if (CastSpell(LIGHTNING_BOLT,pTarget)) { return; }
	}

    //dps
    if (MAELSTROM_WEAPON)
    {
        Aura *maelaura = m_bot->GetAura(MAELSTROM_WEAPON);
        if (maelaura && maelaura->GetStackAmount() == 5)
        {
            if ((isUnderAttack(m_tank,3) || m_tank->GetGUID() == m_bot->GetGUID()) && CastSpell(CHAIN_LIGHTNING,pTarget,true,true)) { return; }
            if (CastSpell(LIGHTNING_BOLT,pTarget,true,true)) { return; }
        }
    }
	if (CastSpell(FLAME_SHOCK,pTarget)) { return; }
    if (CastSpell(STORMSTRIKE,pTarget,true,true)) { return; }

    //if (!TALENT_ENHANCEMENT && CanCast(LAVA_BURST,pTarget,true) && pTarget->HasAura(FLAME_SHOCK,m_bot->GetGUID()) && CastSpell(LAVA_BURST,pTarget,false)) { return; }
	if (CastSpell(FERAL_SPIRIT,m_bot)) { return; }
    if (CanCast(EARTH_SHOCK,pTarget,true) && (pTarget->HasAura(STORMSTRIKE,m_bot->GetGUID()) || pTarget->HasAura(FLAME_SHOCK,m_bot->GetGUID()) ) && CastSpell(EARTH_SHOCK,pTarget)) { return; }
    //if (CanCast(FLAME_SHOCK,pTarget) && CastSpell(FLAME_SHOCK,pTarget)) { return; }
	if (CastSpell(LAVA_LASH,pTarget,true,true)) { return; }
	if (CastSpell(FIRE_NOVA,pTarget)) { return; }
    //if ((isUnderAttack(m_tank,4) || m_tank->GetGUID() == m_bot->GetGUID()) && CastSpell(FIRE_NOVA,pTarget)) { return; }
    if (ai->GetManaPercent() > 60 && castDispel(PURGE,pTarget)) { return; } //PURGE but dont overpurge

    #pragma endregion


    // drink potion if support / healer (Other builds simply overuse mana and waste mana pots)
    if(ai->GetManaPercent() < 5 && (m_role == BOT_ROLE_SUPPORT || m_role == BOT_ROLE_HEALER) )
    {
        Item *pItem = ai->FindPotion();
        if(pItem != NULL)
        {
            if (pItem->GetSpell() && m_bot->HasSpellCooldown(pItem->GetSpell()) ) { return; } //pot is in cooldown
            ai->UseItem(*pItem);
        }
    }


} //end DoNextCombatManeuver
Beispiel #18
0
void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 eventId, Unit* actionInvoker)
{
    switch (action.type)
    {
    case ACTION_T_TEXT:
    {
        if (!action.text.TextId1)
            return;

        int32 temp = action.text.TextId1;

        if (action.text.TextId2 && action.text.TextId3)
            temp = RAND(action.text.TextId1, action.text.TextId2, action.text.TextId3);
        else if (action.text.TextId2 && urand(0, 1))
            temp = action.text.TextId2;

        if (temp)
        {
            Unit* target = NULL;

            if (actionInvoker)
            {
                if (actionInvoker->GetTypeId() == TYPEID_PLAYER)
                    target = actionInvoker;
                else if (Unit* owner = actionInvoker->GetOwner())
                {
                    if (owner->GetTypeId() == TYPEID_PLAYER)
                        target = owner;
                }
            }
            else
            {
                target = me->getVictim();
                if (target && target->GetTypeId() != TYPEID_PLAYER)
                    if (Unit* owner = target->GetOwner())
                        if (owner->GetTypeId() == TYPEID_PLAYER)
                            target = owner;
            }

            DoScriptText(temp, me, target);
        }
        break;
    }
    case ACTION_T_SET_FACTION:
    {
        if (action.set_faction.factionId)
            me->setFaction(action.set_faction.factionId);
        else
        {
            if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(me->GetEntry()))
            {
                //if no id provided, assume reset and then use default
                if (me->getFaction() != ci->faction_A)
                    me->setFaction(ci->faction_A);
            }
        }
        break;
    }
    case ACTION_T_MORPH_TO_ENTRY_OR_MODEL:
    {
        if (action.morph.creatureId || action.morph.modelId)
        {
            //set model based on entry from creature_template
            if (action.morph.creatureId)
            {
                if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(action.morph.creatureId))
                {
                    uint32 display_id = sObjectMgr->ChooseDisplayId(0, ci);
                    me->SetDisplayId(display_id);
                }
            }
            //if no param1, then use value from param2 (modelId)
            else
                me->SetDisplayId(action.morph.modelId);
        }
        else
            me->DeMorph();
        break;
    }
    case ACTION_T_SOUND:
        me->PlayDirectSound(action.sound.soundId);
        break;
    case ACTION_T_EMOTE:
        me->HandleEmoteCommand(action.emote.emoteId);
        break;
    case ACTION_T_RANDOM_SOUND:
    {
        int32 temp = GetRandActionParam(rnd, action.random_sound.soundId1, action.random_sound.soundId2, action.random_sound.soundId3);
        if (temp >= 0)
            me->PlayDirectSound(temp);
        break;
    }
    case ACTION_T_RANDOM_EMOTE:
    {
        int32 temp = GetRandActionParam(rnd, action.random_emote.emoteId1, action.random_emote.emoteId2, action.random_emote.emoteId3);
        if (temp >= 0)
            me->HandleEmoteCommand(temp);
        break;
    }
    case ACTION_T_CAST:
    {
        Unit* target = GetTargetByType(action.cast.target, actionInvoker);
        Unit* caster = me;

        if (!target)
            return;

        if (action.cast.castFlags & CAST_FORCE_TARGET_SELF)
            caster = target;

        //Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
        bool canCast = !caster->IsNonMeleeSpellCasted(false) || (action.cast.castFlags & (CAST_TRIGGERED | CAST_INTERRUPT_PREVIOUS));

        // If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
        if (action.cast.castFlags & CAST_AURA_NOT_PRESENT)
        {
            if (target->HasAura(action.cast.spellId))
                return;
        }

        if (canCast)
        {
            const SpellInfo* tSpell = sSpellMgr->GetSpellInfo(action.cast.spellId);

            //Verify that spell exists
            if (tSpell)
            {
                //Check if cannot cast spell
                if (!(action.cast.castFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)) &&
                        !CanCast(target, tSpell, (action.cast.castFlags & CAST_TRIGGERED)))
                {
                    //Melee current victim if flag not set
                    if (!(action.cast.castFlags & CAST_NO_MELEE_IF_OOM))
                    {
                        if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
                        {
                            m_AttackDistance = 0.0f;
                            m_AttackAngle = 0.0f;

                            me->GetMotionMaster()->MoveChase(me->getVictim(), m_AttackDistance, m_AttackAngle);
                        }
                    }
                }
                else
                {
                    //Interrupt any previous spell
                    if (caster->IsNonMeleeSpellCasted(false) && action.cast.castFlags & CAST_INTERRUPT_PREVIOUS)
                        caster->InterruptNonMeleeSpells(false);

                    caster->CastSpell(target, action.cast.spellId, (action.cast.castFlags & CAST_TRIGGERED));
                }

            }
            else
                sLog->outErrorDb("CreatureEventAI: event %d creature %d attempt to cast spell that doesn't exist %d", eventId, me->GetEntry(), action.cast.spellId);
        }
        break;
    }
    case ACTION_T_SUMMON:
    {
        Unit* target = GetTargetByType(action.summon.target, actionInvoker);

        Creature* creature = NULL;

        if (action.summon.duration)
            creature = me->SummonCreature(action.summon.creatureId, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, action.summon.duration);
        else
            creature = me->SummonCreature(action.summon.creatureId, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);

        if (!creature)
            sLog->outErrorDb("CreatureEventAI: failed to spawn creature %u. Spawn event %d is on creature %d", action.summon.creatureId, eventId, me->GetEntry());
        else if (action.summon.target != TARGET_T_SELF && target)
            creature->AI()->AttackStart(target);
        break;
    }
    case ACTION_T_THREAT_SINGLE_PCT:
        if (Unit* target = GetTargetByType(action.threat_single_pct.target, actionInvoker))
            me->getThreatManager().modifyThreatPercent(target, action.threat_single_pct.percent);
        break;
    case ACTION_T_THREAT_ALL_PCT:
    {
        std::list<HostileReference*>& threatList = me->getThreatManager().getThreatList();
        for (std::list<HostileReference*>::iterator i = threatList.begin(); i != threatList.end(); ++i)
            if (Unit* Temp = Unit::GetUnit(*me, (*i)->getUnitGuid()))
                me->getThreatManager().modifyThreatPercent(Temp, action.threat_all_pct.percent);
        break;
    }
    case ACTION_T_QUEST_EVENT:
        if (Unit* target = GetTargetByType(action.quest_event.target, actionInvoker))
            if (target->GetTypeId() == TYPEID_PLAYER)
                target->ToPlayer()->AreaExploredOrEventHappens(action.quest_event.questId);
        break;
    case ACTION_T_CAST_EVENT:
        if (Unit* target = GetTargetByType(action.cast_event.target, actionInvoker))
            if (target->GetTypeId() == TYPEID_PLAYER)
                target->ToPlayer()->CastedCreatureOrGO(action.cast_event.creatureId, me->GetGUID(), action.cast_event.spellId);
        break;
    case ACTION_T_SET_UNIT_FIELD:
    {
        Unit* target = GetTargetByType(action.set_unit_field.target, actionInvoker);

        // not allow modify important for integrity object fields
        if (action.set_unit_field.field < OBJECT_END || action.set_unit_field.field >= UNIT_END)
            return;

        if (target)
            target->SetUInt32Value(action.set_unit_field.field, action.set_unit_field.value);

        break;
    }
    case ACTION_T_SET_UNIT_FLAG:
        if (Unit* target = GetTargetByType(action.unit_flag.target, actionInvoker))
            target->SetFlag(UNIT_FIELD_FLAGS, action.unit_flag.value);
        break;
    case ACTION_T_REMOVE_UNIT_FLAG:
        if (Unit* target = GetTargetByType(action.unit_flag.target, actionInvoker))
            target->RemoveFlag(UNIT_FIELD_FLAGS, action.unit_flag.value);
        break;
    case ACTION_T_AUTO_ATTACK:
        m_MeleeEnabled = action.auto_attack.state != 0;
        break;
    case ACTION_T_COMBAT_MOVEMENT:
        // ignore no affect case
        if (m_CombatMovementEnabled == (action.combat_movement.state != 0))
            return;

        m_CombatMovementEnabled = action.combat_movement.state != 0;

        //Allow movement (create new targeted movement gen only if idle)
        if (m_CombatMovementEnabled)
        {
            Unit* victim = me->getVictim();
            if (me->isInCombat() && victim)
            {
                if (action.combat_movement.melee)
                {
                    me->AddUnitState(UNIT_STATE_MELEE_ATTACKING);
                    me->SendMeleeAttackStart(victim);
                }
                if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == IDLE_MOTION_TYPE)
                    me->GetMotionMaster()->MoveChase(victim, m_AttackDistance, m_AttackAngle); // Targeted movement generator will start melee automatically, no need to send it explicitly
            }
        }
        else
        {
            if (me->isInCombat())
            {
                Unit* victim = me->getVictim();
                if (action.combat_movement.melee && victim)
                {
                    me->ClearUnitState(UNIT_STATE_MELEE_ATTACKING);
                    me->SendMeleeAttackStop(victim);
                }
                if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
                    me->GetMotionMaster()->MoveIdle();
            }
        }
        break;
    case ACTION_T_SET_PHASE:
        m_Phase = action.set_phase.phase;
        break;
    case ACTION_T_INC_PHASE:
    {
        int32 new_phase = int32(m_Phase)+action.set_inc_phase.step;
        if (new_phase < 0)
        {
            sLog->outErrorDb("CreatureEventAI: Event %d decrease m_Phase under 0. CreatureEntry = %d", eventId, me->GetEntry());
            m_Phase = 0;
        }
        else if (new_phase >= MAX_PHASE)
        {
            sLog->outErrorDb("CreatureEventAI: Event %d incremented m_Phase above %u. m_Phase mask cannot be used with phases past %u. CreatureEntry = %d", eventId, MAX_PHASE-1, MAX_PHASE-1, me->GetEntry());
            m_Phase = MAX_PHASE-1;
        }
        else
            m_Phase = new_phase;

        break;
    }
    case ACTION_T_EVADE:
        EnterEvadeMode();
        break;
    case ACTION_T_FLEE_FOR_ASSIST:
        me->DoFleeToGetAssistance();
        break;
    case ACTION_T_QUEST_EVENT_ALL:
        if (actionInvoker && actionInvoker->GetTypeId() == TYPEID_PLAYER)
        {
            if (Unit* Temp = Unit::GetUnit(*me, actionInvoker->GetGUID()))
                if (Temp->GetTypeId() == TYPEID_PLAYER)
                    Temp->ToPlayer()->GroupEventHappens(action.quest_event_all.questId, me);
        }
        break;
    case ACTION_T_CAST_EVENT_ALL:
    {
        std::list<HostileReference*>& threatList = me->getThreatManager().getThreatList();
        for (std::list<HostileReference*>::iterator i = threatList.begin(); i != threatList.end(); ++i)
            if (Unit* Temp = Unit::GetUnit(*me, (*i)->getUnitGuid()))
                if (Temp->GetTypeId() == TYPEID_PLAYER)
                    Temp->ToPlayer()->CastedCreatureOrGO(action.cast_event_all.creatureId, me->GetGUID(), action.cast_event_all.spellId);
        break;
    }
    case ACTION_T_REMOVEAURASFROMSPELL:
        if (Unit* target = GetTargetByType(action.remove_aura.target, actionInvoker))
            target->RemoveAurasDueToSpell(action.remove_aura.spellId);
        break;
    case ACTION_T_RANGED_MOVEMENT:
        m_AttackDistance = (float)action.ranged_movement.distance;
        m_AttackAngle = action.ranged_movement.angle/180.0f*M_PI;

        if (m_CombatMovementEnabled)
        {
            me->GetMotionMaster()->MoveChase(me->getVictim(), m_AttackDistance, m_AttackAngle);
        }
        break;
    case ACTION_T_RANDOM_PHASE:
        m_Phase = GetRandActionParam(rnd, action.random_phase.phase1, action.random_phase.phase2, action.random_phase.phase3);
        break;
    case ACTION_T_RANDOM_PHASE_RANGE:
        if (action.random_phase_range.phaseMin <= action.random_phase_range.phaseMax)
            m_Phase = urand(action.random_phase_range.phaseMin, action.random_phase_range.phaseMax);
        else
            sLog->outErrorDb("CreatureEventAI: ACTION_T_RANDOM_PHASE_RANGE cannot have Param2 < Param1. Event = %d. CreatureEntry = %d", eventId, me->GetEntry());
        break;
    case ACTION_T_SUMMON_ID:
    {
        Unit* target = GetTargetByType(action.summon_id.target, actionInvoker);

        CreatureEventAI_Summon_Map::const_iterator i = sEventAIMgr->GetCreatureEventAISummonMap().find(action.summon_id.spawnId);
        if (i == sEventAIMgr->GetCreatureEventAISummonMap().end())
        {
            sLog->outErrorDb("CreatureEventAI: failed to spawn creature %u. Summon map index %u does not exist. EventID %d. CreatureID %d", action.summon_id.creatureId, action.summon_id.spawnId, eventId, me->GetEntry());
            return;
        }

        Creature* creature = NULL;
        if ((*i).second.SpawnTimeSecs)
            creature = me->SummonCreature(action.summon_id.creatureId, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs);
        else
            creature = me->SummonCreature(action.summon_id.creatureId, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);

        if (!creature)
            sLog->outErrorDb("CreatureEventAI: failed to spawn creature %u. EventId %d.Creature %d", action.summon_id.creatureId, eventId, me->GetEntry());
        else if (action.summon_id.target != TARGET_T_SELF && target)
            creature->AI()->AttackStart(target);

        break;
    }
    case ACTION_T_KILLED_MONSTER:
        //first attempt player who tapped creature
        if (Player* player = me->GetLootRecipient())
            player->RewardPlayerAndGroupAtEvent(action.killed_monster.creatureId, player);    // player as param is a hacky solution not to use GUID
        else
        {
            //if not available, use actionInvoker
            if (Unit* target = GetTargetByType(action.killed_monster.target, actionInvoker))
                if (Player* player2 = target->GetCharmerOrOwnerPlayerOrPlayerItself())
                    player2->RewardPlayerAndGroupAtEvent(action.killed_monster.creatureId, player2);
        }
        break;
    case ACTION_T_SET_INST_DATA:
    {
        InstanceScript* instance = (InstanceScript*)me->GetInstanceScript();
        if (!instance)
        {
            sLog->outErrorDb("CreatureEventAI: Event %d attempt to set instance data without instance script. Creature %d", eventId, me->GetEntry());
            return;
        }

        instance->SetData(action.set_inst_data.field, action.set_inst_data.value);
        break;
    }
    case ACTION_T_SET_INST_DATA64:
    {
        Unit* target = GetTargetByType(action.set_inst_data64.target, actionInvoker);
        if (!target)
        {
            sLog->outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 but Target == NULL. Creature %d", eventId, me->GetEntry());
            return;
        }

        InstanceScript* instance = (InstanceScript*)me->GetInstanceScript();
        if (!instance)
        {
            sLog->outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 without instance script. Creature %d", eventId, me->GetEntry());
            return;
        }

        instance->SetData64(action.set_inst_data64.field, target->GetGUID());
        break;
    }
    case ACTION_T_UPDATE_TEMPLATE:
        if (me->GetEntry() == action.update_template.creatureId)
        {

            sLog->outErrorDb("CreatureEventAI: Event %d ACTION_T_UPDATE_TEMPLATE call with param1 == current entry. Creature %d", eventId, me->GetEntry());
            return;
        }

        me->UpdateEntry(action.update_template.creatureId, action.update_template.team ? HORDE : ALLIANCE);
        break;
    case ACTION_T_DIE:
        if (me->isDead())
        {

            sLog->outErrorDb("CreatureEventAI: Event %d ACTION_T_DIE on dead creature. Creature %d", eventId, me->GetEntry());
            return;
        }
        me->Kill(me);
        break;
    case ACTION_T_ZONE_COMBAT_PULSE:
    {
        me->SetInCombatWithZone();
        break;
    }
    case ACTION_T_CALL_FOR_HELP:
    {
        me->CallForHelp((float)action.call_for_help.radius);
        break;
    }
    break;

    // TRINITY ONLY
    case ACTION_T_MOVE_RANDOM_POINT: //dosen't work in combat
    {
        float x, y, z;
        me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, (float)action.raw.param1);
        me->GetMotionMaster()->MovePoint(0, x, y, z);
        break;
    }
    case ACTION_T_SET_STAND_STATE:
        me->SetStandState(UnitStandStateType(action.raw.param1));
        break;
    case ACTION_T_SET_PHASE_MASK:
        me->SetPhaseMask(action.raw.param1, true);
        break;
    case ACTION_T_SET_VISIBILITY:
        me->SetVisible(bool(action.raw.param1));
        break;
    case ACTION_T_SET_ACTIVE:
        me->setActive(action.raw.param1 ? true : false);
        break;
    case ACTION_T_SET_AGGRESSIVE:
        me->SetReactState(ReactStates(action.raw.param1));
        break;
    case ACTION_T_ATTACK_START_PULSE:
        AttackStart(me->SelectNearestTarget((float)action.raw.param1));
        break;
    case ACTION_T_SUMMON_GO:
    {
        GameObject* object = NULL;

        float x, y, z;
        me->GetPosition(x, y, z);
        object = me->SummonGameObject(action.raw.param1, x, y, z, 0, 0, 0, 0, 0, action.raw.param2);
        if (!object)
        {
            sLog->outErrorDb("TSCR: EventAI failed to spawn object %u. Spawn event %d is on creature %d", action.raw.param1, eventId, me->GetEntry());
        }
        break;
    }

    case ACTION_T_SET_SHEATH:
    {
        me->SetSheath(SheathState(action.set_sheath.sheath));
        break;
    }
    case ACTION_T_FORCE_DESPAWN:
    {
        me->DespawnOrUnsummon(action.forced_despawn.msDelay);
        break;
    }
    case ACTION_T_SET_INVINCIBILITY_HP_LEVEL:
    {
        if (action.invincibility_hp_level.is_percent)
            m_InvincibilityHpLevel = me->CountPctFromMaxHealth(action.invincibility_hp_level.hp_level);
        else
            m_InvincibilityHpLevel = action.invincibility_hp_level.hp_level;
        break;
    }
    case ACTION_T_MOUNT_TO_ENTRY_OR_MODEL:
    {
        if (action.mount.creatureId || action.mount.modelId)
        {
            // set model based on entry from creature_template
            if (action.mount.creatureId)
            {
                if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(action.mount.creatureId))
                {
                    uint32 display_id = sObjectMgr->ChooseDisplayId(0, cInfo);
                    me->Mount(display_id);
                }
            }
            //if no param1, then use value from param2 (modelId)
            else
                me->Mount(action.mount.modelId);
        }
        else
            me->Dismount();

        break;
    }
    }
}
Beispiel #19
0
            void DoNonCombatActions()
            {
                Feast();

                if (isTimerReady(uiGc_Timer) && !me->HasAura(SPELL_LIGHTNING_SHIELD, 0))
                doCast(me, SPELL_LIGHTNING_SHIELD);

                if (master->GetGroup())
                {
                    RezGroup(SPELL_ANCESTRAL_SPIRIT, master);
                    BuffAndHealGroup(master);
                }

                /* TESTING */
                Group::MemberSlotList const &a =((Player*)master)->GetGroup()->GetMemberSlots();

                for (Group::member_citerator itr = a.begin(); itr != a.end(); itr++)
                {
                    Player* tPlayer = ((Player *)master)->GetObjPlayer(itr->guid);
            
                    if (tPlayer == NULL)
                        continue;
            
                    //healing others
                    if (tPlayer->isAlive() && isTimerReady(uiOthersHeal_Timer) && tPlayer->GetGUID() != master->GetGUID() && tPlayer->GetHealth() * 100 / tPlayer->GetMaxHealth() < 75 && CanCast(tPlayer, GetSpellStore()->LookupEntry(SPELL_CHAIN_HEAL)))
                    {
                        doCast(tPlayer, SPELL_CHAIN_HEAL, false);
                        uiOthersHeal_Timer = 100;
                    }

                    //rezzes
                    if (tPlayer->isDead() && !me->isInCombat() && me->GetDistance(tPlayer) < 40 && isTimerReady(uiRez_Timer))
                    {
                        char* str = (char *)malloc(32);
                        sprintf(str, "Resucitando a %s", tPlayer->GetName());
                        me->MonsterSay(str, LANG_UNIVERSAL, NULL);
                        free(str);
                        doCast(tPlayer, SPELL_ANCESTRAL_SPIRIT, false);
                        uiRez_Timer = 160;
                    }
                }

                /* TESTING */
                if ((master->GetHealth() * 100 / master->GetMaxHealth() < 90) && uiLesserHealing_Timer <= 0)
                {
                    doCast(master, SPELL_LESSER_HEALING);
                    uiLesserHealing_Timer = 90;
                    uiHeal_Timer = uiHeal_Timer + 5; //wait 5 seconds before casting a real heal
                    return;
                }
                else if (uiLesserHealing_Timer >= 0)
                    --uiLesserHealing_Timer;

                if ((master->GetHealth() * 100 / master->GetMaxHealth() < 75) && isTimerReady(uiHeal_Timer))
                {
                    doCast(master, SPELL_CHAIN_HEAL);
                    uiHeal_Timer = 10;
                }

                if (me->GetHealth() * 100 / me->GetMaxHealth() < 90)
                {
                    if (uiSelfLesserHealing_Timer <= 0)
                    {
                        doCast(me, SPELL_LESSER_HEALING);
                        uiSelfLesserHealing_Timer = 90;
                        return;
                    }
                    else if (uiSelfLesserHealing_Timer >= 0)
                    --uiSelfLesserHealing_Timer;
                }
            }
Beispiel #20
0
            void UpdateAI(const uint32 diff)
            {
                DoMeleeAttackIfReady();

                decrementTimers();

                if (IAmDead())
                    return;

                if (me->GetPower(POWER_MANA) < 400 && isTimerReady(uiPotion_Timer))
                {
                    doCast(me, SPELL_MANA_POTION);
                    uiPotion_Timer = 150;
                }

                if (me->GetPower(POWER_MANA)/me->GetMaxPower(POWER_MANA) < 10)
                {
                    if (uiOom_Timer == 0)
                        uiOom_Timer = 1;
                }

                BuffAndHealGroup(master);

                // Heal myself
                HealTarget (me, me->GetHealth() * 100 / me->GetMaxHealth());

                //the rest are combat so return if not fighting
                opponent = SelectTarget(SELECT_TARGET_TOPAGGRO, 0);

                if (!opponent && !me->getVictim())
                {
                    DoNonCombatActions();
                    ResetOrGetNextTarget();
                    return;
                }

                //Cast totems.
                if (me->isInCombat() && isTimerReady(uiEarthTotem_Timer) && !master->HasAura(SPELL_STONE_SKIN_AURA, 0))
                {
                    doCast(me, SPELL_STONE_SKIN_TOTEM);
                    GiveManaBack();
                    uiEarthTotem_Timer = 90;
                    return;
                }

                if (me->isInCombat() && isTimerReady(uiFireTotem_Timer))
                {
                    doCast(me, SPELL_SEARING_TOTEM);
                    GiveManaBack();
                    uiFireTotem_Timer = 180;
                    return;
                }

                if (me->isInCombat() && isTimerReady(uiWindTotem_Timer))
                {
                    doCast(me, SPELL_WINDFURY_TOTEM);
                    GiveManaBack();
                    uiWindTotem_Timer = 180;
                    return;
                }

                if (me->isInCombat())
                {
                    switch(master->getClass())
                    {
                        case CLASS_WARRIOR:
                        case CLASS_DEATH_KNIGHT:
                        case CLASS_ROGUE:
                            if (isTimerReady(uiWaterTotem_Timer) && !master->HasAura(SPELL_HEALING_STREAM_AURA))
                            {
                                doCast(me, SPELL_HEALING_STREAM_TOTEM);
                                uiWaterTotem_Timer = 90;
                                GiveManaBack();
                                return;
                            }
                            break;
                        default: //everyone else gets a mana totem
                            if (isTimerReady (uiWaterTotem_Timer) && !master->HasAura(SPELL_MANA_SPRING_AURA, 0))
                            {
                                doCast(me, SPELL_MANA_SPRING_TOTEM);
                                uiWaterTotem_Timer = 90;
                                GiveManaBack();
                                return;
                            }
                    }
                }

                if (isTimerReady(uiFlameShock_Timer))
                {
                    doCast(opponent, SPELL_FLAME_SHOCK);
                    uiFlameShock_Timer = 120;
                    return;
                }

                if (isTimerReady(uiLightningBolt_Timer))
                {
                    doCast(opponent, SPELL_LIGHTNING_BOLT);
                    uiLightningBolt_Timer = 180;
                    return;
                }

                if (isTimerReady(uiEarthShock_Timer))
                {
                    doCast(opponent, SPELL_EARTH_SHOCK);
                    uiEarthShock_Timer = 250;
                    return;
                }

                //now try to heal bots and pets.  DoSelectLowestHpFriendly will get
                //everyone in group including bots and pets.  Unfortunately it can
                //not be triggered for % of lost HP, so we just set it to -1000.
                //This means low level players wont be healed because they wont have
                //enough HP.
                Unit* target = DoSelectLowestHpFriendly(40, 1000);

                if (target)
                {
                    if (CanCast(target, GetSpellStore()->LookupEntry (SPELL_CHAIN_HEAL)))
                    {
                        doCast(target, SPELL_CHAIN_HEAL, false);
                        uiOthersHeal_Timer = 50;
                    }
                }
                else
                {
                    target = DoSelectLowestHpFriendly(40, 500); //now try someone with less HP lost

                    if (target)
                    {
                        if (CanCast(target, GetSpellStore()->LookupEntry (SPELL_CHAIN_HEAL)))
                        {
                            doCast(target, SPELL_CHAIN_HEAL, false);
                            uiOthersHeal_Timer = 100;
                        }
                    }
                }

                ScriptedAI::UpdateAI(diff);
            }
bool PlayerbotClassAI::castSelfCCBreakers (uint32 castList[])
{
    uint32 dispelSpell = 0;
    Player *dTarget = GetPlayerBot();


            /* dispelSpell = (uint32) R_ESCAPE_ARTIST; // this is script effect,
            Unit::AuraMap const& auras = dTarget->GetOwnedAuras();
            for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); itr++)
            {
                Aura * aura = itr->second;
                AuraApplication * aurApp = aura->GetApplicationOfTarget(dTarget->GetGUID());
                if (!aurApp)
                    continue;

                if ( ( aura->GetSpellProto()->Mechanic == MECHANIC_SNARE ) || ( aura->GetSpellProto()->Mechanic == MECHANIC_ROOT ) )
                {
                    if(aura->GetSpellProto()->Dispel == DISPEL_MAGIC)
                    {
                        bool positive = aurApp->IsPositive() ? (!(aura->GetSpellProto()->AttributesEx & SPELL_ATTR0_UNK7)) : false;

                        // do not remove positive auras if friendly target
                        //               negative auras if non-friendly target
                        if(positive == dTarget->IsFriendlyTo(caster))
                            continue;
                    }
                    return castSpell(dispelSpell, dTarget);
                }
            }
            return false;  */

        // racial abilities
    /*  if( GetPlayerBot()->getRace() == RACE_BLOODELF && !pTarget->HasAura( ARCANE_TORRENT,0 ) && castSpell( ARCANE_TORRENT,pTarget ) ) {
         //GetPlayerBot()->Say("Arcane Torrent!", LANG_UNIVERSAL);
    } else if( GetPlayerBot()->getRace() == RACE_HUMAN && (GetPlayerBot()->HasUnitState( UNIT_STAT_STUNNED ) || GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_FEAR ) || GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_DECREASE_SPEED ) || GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_CHARM )) && castSpell( EVERY_MAN_FOR_HIMSELF, GetPlayerBot() ) ) {
        //GetPlayerBot()->Say("EVERY MAN FOR HIMSELF!", LANG_UNIVERSAL);
    } else if( GetPlayerBot()->getRace() == RACE_UNDEAD_PLAYER && (GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_FEAR ) || GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_CHARM )) && castSpell( WILL_OF_THE_FORSAKEN, GetPlayerBot() ) ) {
       // GetPlayerBot()->Say("WILL OF THE FORSAKEN!", LANG_UNIVERSAL);
    } else if( GetPlayerBot()->getRace() == RACE_DWARF && GetPlayerBot()->HasAuraState( AURA_STATE_DEADLY_POISON ) && castSpell( STONEFORM, GetPlayerBot() ) ) {
        //GetPlayerBot()->Say("STONEFORM!", LANG_UNIVERSAL);
    } else if( GetPlayerBot()->getRace() == RACE_GNOME && (GetPlayerBot()->HasUnitState( UNIT_STAT_STUNNED ) || GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_DECREASE_SPEED )) && castSpell( ESCAPE_ARTIST, GetPlayerBot() ) ) {
       // GetPlayerBot()->Say("ESCAPE ARTIST!", LANG_UNIVERSAL);
    } */

    for (uint8 j = 0; j <  sizeof (castList); j++)
    {
        dispelSpell = castList[j];
        if (dispelSpell == 0 || !dTarget->HasSpell(dispelSpell) || !CanCast(dispelSpell, dTarget, true)) continue;
        SpellEntry const *dSpell = GetSpellStore()->LookupEntry(dispelSpell);
        if (!dSpell) continue;

        for (uint8 i = 0 ; i < MAX_SPELL_EFFECTS ; ++i)
        {
            if (dSpell->Effect[i] != (uint32)SPELL_EFFECT_DISPEL && dSpell->Effect[i] != (uint32)SPELL_EFFECT_APPLY_AURA) continue;
            if (dSpell->Effect[i] == (uint32)SPELL_EFFECT_APPLY_AURA && (
                (dSpell->EffectApplyAuraName[i] != (uint32) SPELL_AURA_MECHANIC_IMMUNITY) ||
                (dSpell->EffectApplyAuraName[i] != (uint32) SPELL_AURA_DISPEL_IMMUNITY)
                )) continue;

            Unit::AuraMap const& auras = dTarget->GetOwnedAuras();
            for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); itr++)
            {
                Aura * aura = itr->second;
                AuraApplication * aurApp = aura->GetApplicationOfTarget(dTarget->GetGUID());
                if (!aurApp) continue;

                if (aura->GetSpellProto() && (
                    (dSpell->Effect[i] == (uint32)SPELL_EFFECT_DISPEL  && ((1<<aura->GetSpellProto()->Dispel) & GetDispellMask(DispelType(dSpell->EffectMiscValue[i]))) )
                    || (dSpell->EffectApplyAuraName[i] == (uint32) SPELL_AURA_MECHANIC_IMMUNITY && ( GetAllSpellMechanicMask(aura->GetSpellProto()) & ( 1 << dSpell->EffectMiscValue[i]) ) )
                    || (dSpell->EffectApplyAuraName[i] == (uint32) SPELL_AURA_DISPEL_IMMUNITY && ( (1<<aura->GetSpellProto()->Dispel) & GetDispellMask(DispelType(dSpell->EffectMiscValue[i])) ) )
                    ) )
                {
                    if(aura->GetSpellProto()->Dispel == DISPEL_MAGIC)
                    {
                        bool positive = aurApp->IsPositive() ? (!(aura->GetSpellProto()->AttributesEx & SPELL_ATTR0_UNK7)) : false;
                        if(positive)continue;
                    }
                    return CastSpell(dispelSpell, dTarget, false);
                }
            }
        }
    }
    return false;
}
void PlayerbotDeathKnightAI::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);

    Pet *pet = m_bot->GetPet();
    std::ostringstream out;


    if (!m_pulling)
    {
        m_role = BOT_ROLE_DPS_MELEE;
        #pragma region Choose Role/Presence

        // Choose Presence
        if (m_tank->GetGUID() == m_bot->GetGUID()) // Hey! I am Main Tank
        {
            if (CastSpell(FROST_PRESENCE,m_bot)) { m_role = BOT_ROLE_TANK; return; }
        }
        else if (isUnderAttack()) // I am under attack
        {
            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
            //if (m_bot->getRace() == (uint8) RACE_NIGHTELF && CastSpell(R_SHADOWMELD,m_bot) ) { return; }
            if (CastSpell(FROST_PRESENCE,m_bot)) { m_role = BOT_ROLE_OFFTANK; return; }
        }
        else if (TALENT_UNHOLY)
        {
            if (CastSpell(UNHOLY_PRESENCE,m_bot)) return;
        }
        else if (CastSpell(BLOOD_PRESENCE,m_bot)) return;
        #pragma endregion
    }

    // Cast CC breakers if any match found  (does not work yet)
    // uint32 ccSpells[6] = { LICHBORNE, ICEBOUND_FORTITUDE, R_ESCAPE_ARTIST, R_EVERY_MAN_FOR_HIMSELF, R_WILL_OF_FORSAKEN, R_STONEFORM };
    // if (castSelfCCBreakers(ccSpells)) { } //most of them dont have gcd

    TakePosition(pTarget);


   if (m_pulling) {
        if (GetAI()->CastSpell(DEATH_GRIP,pTarget)) {
            m_pulling = false;
            GetAI()->SetCombatOrder(ORDERS_NONE);
            GetAI()->Follow(*GetMaster());
            GetAI()->SetIgnoreUpdateTime(2);

            if (m_bot->GetPet()) pet->SetReactState (REACT_DEFENSIVE);
         }
          return;
    }

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

    #pragma region Buff Heal Interrupt
    //Buff UP
    if (CastSpell(HORN_OF_WINTER,m_bot)) { return; }
    if (CastSpell(BONE_SHIELD,m_bot)) { return; }

    //HEAL UP && PROTECT UP
    if (ai->GetHealthPercent() < 80 && ai->GetHealthPercent() > 20 && CastSpell(VAMPIRIC_BLOOD,m_bot)) { }  //NO GCD
    if (ai->GetHealthPercent() < 65 && CastSpell(RUNE_TAP,m_bot)) { } //NO GCD
    if (CanCast(DEATH_STRIKE,pTarget,true) && ai->GetHealthPercent() < 90 &&
        (pTarget->HasAura(FROST_FEVER,m_bot->GetGUID()) ||pTarget->HasAura(BLOOD_PLAGUE,m_bot->GetGUID()) )
        && CastSpell(DEATH_STRIKE,pTarget,false) ) {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 (pet && ai->GetHealthPercent() < 50 && CastSpell(DEATH_PACT,m_bot)) { return; }
    if (pet && ai->GetHealthPercent() < 60 && CastSpell(MARK_OF_BLOOD,pTarget)) { return; }
    if (ai->GetHealthPercent() < 65 && CastSpell(ICEBOUND_FORTITUDE,m_bot)) { } //No GCD
    if (ai->GetHealthPercent() < 65 && CastSpell(UNBREAKABLE_ARMOR,m_bot)) { return; }

    //Break spells being cast
    if (pTarget->IsNonMeleeSpellCasted(true))
    {
        if (CastSpell(MIND_FREEZE,pTarget)) {} // No GCD
        if (CastSpell(STRANGULATE,pTarget)) { return; }
        if (m_bot->getRace() == (uint8) RACE_BLOODELF && pDist < 8 && CastSpell(R_ARCANE_TORRENT, pTarget)) { } //no gcd
        if (CastSpell(ANTI_MAGIC_ZONE,m_bot)) { return; }
        if (CastSpell(ANTI_MAGIC_SHELL,m_bot)) {} //NO GCD
    }

    //Catch
    if (pTarget->HasUnitMovementFlag(UNIT_FLAG_FLEEING))
    {
        if (CastSpell(DEATH_GRIP,pTarget)) return;
        if (CastSpell(CHAINS_OF_ICE,pTarget)) return;
    }
    #pragma endregion

    #pragma region Taunt / Threat
    // if i am main tank, protect master by taunt
    if(m_tank->GetGUID() == m_bot->GetGUID())
    {
        // Taunt if needed (Only for master)
        Unit *curAtt = GetAttackerOf(GetMaster());
        if (curAtt && CastSpell(DARK_COMMAND, curAtt))  { }     //No gcd
        // My target is not attacking me, taunt..
        if (pVictim && pVictim->GetGUID() != m_bot->GetGUID() && CastSpell(DARK_COMMAND, pTarget) )  { } // No gcd
    }

    // If not in Frost Presence slow down due to threat
    if (pThreat > threatThreshold && !m_bot->HasAura(FROST_PRESENCE) && 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 { return; } //DK has no threat reducing spells, just slow down
    }
    #pragma endregion

    #pragma region Dps
    //Dps up
    if (CastSpell(EMPOWER_WEAPON,m_bot)) {} //NO GCD
    if (ai->GetHealthPercent() > 90 && CastSpell(HYSTERIA,m_bot)) {} //NO GCD
    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

    // Use up excess Runic Power
    if (ai->GetRunicPower() > 60 && CastSpell(FROST_STRIKE,pTarget)) { return; }
    else if (ai->GetRunicPower() > 60 && CastSpell(DEATH_COIL,pTarget,true,true,true)) { return; }
    if ((isUnderAttack() || ai->GetRunicPower() > 70) && CastSpell(RUNE_STRIKE,pTarget)) {} //Next attack spell

    // Build Diseases
    if (!pTarget->HasAura(FROST_FEVER,m_bot->GetGUID()) && CastSpell(ICY_TOUCH,pTarget)) { return; }
    if (!pTarget->HasAura(BLOOD_PLAGUE,m_bot->GetGUID()) && CastSpell(PLAGUE_STRIKE,pTarget)) { return; }

    // Use AOEs summons
    if (isUnderAttack(m_tank,4) && CastSpell(DEATH_AND_DECAY,pTarget)) { return; }
    if (isUnderAttack(m_tank,4) && CastSpell(HOWLING_BLAST,pTarget)) { return; }
    if (CanCast(PESTILENCE,pTarget,true) && isUnderAttack(m_tank,4) &&
        (pTarget->HasAura(FROST_FEVER,m_bot->GetGUID()) && pTarget->HasAura(BLOOD_PLAGUE,m_bot->GetGUID()) )
        && CastSpell(PESTILENCE,pTarget,false)) { return; }
    if (CanCast(BLOOD_BOIL,pTarget,true) && isUnderAttack(m_tank,4) &&
        (pTarget->HasAura(FROST_FEVER,m_bot->GetGUID()) || pTarget->HasAura(BLOOD_PLAGUE,m_bot->GetGUID()) )
        && CastSpell(BLOOD_BOIL,pTarget,false)) { return; }
    if (m_bot->getRace() == (uint8) RACE_TAUREN && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return; } //no gcd but is cast
    if (isUnderAttack(m_tank,6) && CastSpell(ARMY_OF_THE_DEAD,m_bot)) { return; }
    if (isUnderAttack(m_tank,4) && CastSpell(SUMMON_GARGOYLE,pTarget)) { return; } //This should be somewhat different

    // Use standard damage spells
    if (CastSpell(HEART_STRIKE,pTarget,true,true)) { return; }
    if (CastSpell(BLOOD_STRIKE,pTarget)) { return; }
    if (TALENT_FROST && CastSpell(OBLITERATE,pTarget)) { return; }
    else if (TALENT_UNHOLY && CastSpell(SCOURGE_STRIKE,pTarget)) { return; }
    else if (CastSpell(DEATH_STRIKE,pTarget)) { return; }
    #pragma endregion

} // end DoNextCombatManeuver