Example #1
0
Unit* PartyMemberToHeal::Calculate()
{
    
    IsTargetOfHealingSpell predicate;

    Group* group = bot->GetGroup();
    if (!group)
        return NULL;

    bool isRaid = bot->GetGroup()->isRaidGroup();
    MinValueCalculator calc(100);
    for (GroupReference *gref = group->GetFirstMember(); gref; gref = gref->next()) 
    {
        Player* player = gref->getSource();
        if (!Check(player) || !player->IsAlive())
            continue;

        uint8 health = player->GetHealthPercent();
        if (isRaid || health < sPlayerbotAIConfig.mediumHealth || !IsTargetOfSpellCast(player, predicate))
            calc.probe(health, player);

        Pet* pet = player->GetPet();
        if (pet && CanHealPet(pet)) 
        {
            health = pet->GetHealthPercent();
            if (isRaid || health < sPlayerbotAIConfig.mediumHealth || !IsTargetOfSpellCast(player, predicate))
                calc.probe(health, player);
        }
    }
    return (Unit*)calc.param;
}
Example #2
0
void PlayerbotWarlockAI::DoNonCombatActions()
{
    SpellSequence = SPELL_CURSES;

    PlayerbotAI *ai = GetAI();
    Player * m_bot = GetPlayerBot();
    if (!ai || !m_bot)
        return;

    Pet *pet = m_bot->GetPet();

    // Initialize pet spells
    if (pet && pet->GetEntry() != m_lastDemon)
    {
        switch (pet->GetEntry())
        {
            case DEMON_IMP:
            {
                BLOOD_PACT       = ai->initPetSpell(BLOOD_PACT_ICON);
                FIREBOLT         = ai->initPetSpell(FIREBOLT_ICON);
                FIRE_SHIELD      = ai->initPetSpell(FIRE_SHIELD_ICON);
                break;
            }
            case DEMON_VOIDWALKER:
            {
                CONSUME_SHADOWS  = ai->initPetSpell(CONSUME_SHADOWS_ICON);
                SACRIFICE        = ai->initPetSpell(SACRIFICE_ICON);
                SUFFERING        = ai->initPetSpell(SUFFERING_ICON);
                TORMENT          = ai->initPetSpell(TORMENT_ICON);
                break;
            }
            case DEMON_SUCCUBUS:
            {
                LASH_OF_PAIN     = ai->initPetSpell(LASH_OF_PAIN_ICON);
                SEDUCTION        = ai->initPetSpell(SEDUCTION_ICON);
                SOOTHING_KISS    = ai->initPetSpell(SOOTHING_KISS_ICON);
                break;
            }
            case DEMON_FELHUNTER:
            {
                DEVOUR_MAGIC     = ai->initPetSpell(DEVOUR_MAGIC_ICON);
                FEL_INTELLIGENCE = ai->initPetSpell(FEL_INTELLIGENCE_ICON);
                SHADOW_BITE      = ai->initPetSpell(SHADOW_BITE_ICON);
                SPELL_LOCK       = ai->initPetSpell(SPELL_LOCK_ICON);
                break;
            }
            case DEMON_FELGUARD:
            {
                ANGUISH          = ai->initPetSpell(ANGUISH_ICON);
                CLEAVE           = ai->initPetSpell(CLEAVE_ICON);
                INTERCEPT        = ai->initPetSpell(INTERCEPT_ICON);
                break;
            }
        }

        m_lastDemon = pet->GetEntry();

        if (!m_isTempImp)
            m_demonOfChoice = pet->GetEntry();
    }

    // Destroy extra soul shards
    uint8 shardCount = m_bot->GetItemCount(SOUL_SHARD, false, NULL);
    uint8 freeSpace = ai->GetFreeBagSpace();
    if (shardCount > MAX_SHARD_COUNT || (freeSpace == 0 && shardCount > 1))
        m_bot->DestroyItemCount(SOUL_SHARD, shardCount > MAX_SHARD_COUNT ? shardCount - MAX_SHARD_COUNT : 1, true, false);

    // buff myself DEMON_SKIN, DEMON_ARMOR, FEL_ARMOR
    if (FEL_ARMOR)
    {
        if (ai->SelfBuff(FEL_ARMOR))
            return;
    }
    else if (DEMON_ARMOR)
    {
        if (ai->SelfBuff(DEMON_ARMOR))
            return;
    }
    else if (DEMON_SKIN)
        if (ai->SelfBuff(DEMON_SKIN))
            return;

    // healthstone creation
    if (CREATE_HEALTHSTONE && shardCount > 0)
    {
        Item* const healthStone = ai->FindConsumable(HEALTHSTONE_DISPLAYID);
        if (!healthStone && ai->CastSpell(CREATE_HEALTHSTONE))
            return;
    }

    // soulstone creation and use
    if (CREATE_SOULSTONE)
    {
        Item* soulStone = ai->FindConsumable(SOULSTONE_DISPLAYID);
        if (!soulStone)
        {
            if (shardCount > 0 && !m_bot->HasSpellCooldown(CREATE_SOULSTONE) && ai->CastSpell(CREATE_SOULSTONE))
                return;
        }
        else
        {
            uint32 soulStoneSpell = soulStone->GetProto()->Spells[0].SpellId;
            Player * master = GetMaster();
            if (!master->HasAura(soulStoneSpell) && !m_bot->HasSpellCooldown(soulStoneSpell))
            {
                ai->UseItem(soulStone, master);
                return;
            }
        }
    }

    // firestone creation and use
    Item* const weapon = m_bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
    if (weapon && weapon->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT) == 0)
    {
        Item* const stone = ai->FindConsumable(FIRESTONE_DISPLAYID);
        if (!stone)
        {
            if (CREATE_FIRESTONE && shardCount > 0 && ai->CastSpell(CREATE_FIRESTONE))
                return;
        }
        else
        {
            ai->UseItem(stone, EQUIPMENT_SLOT_MAINHAND);
            return;
        }
    }

    if (m_bot->getStandState() != UNIT_STAND_STATE_STAND)
        m_bot->SetStandState(UNIT_STAND_STATE_STAND);

    // mana check
    if (pet && DARK_PACT && pet->GetPower(POWER_MANA) > 0 && ai->GetManaPercent() <= 50)
        if (ai->CastSpell(DARK_PACT, *m_bot))
            return;

    if (LIFE_TAP && ai->GetManaPercent() <= 50 && ai->GetHealthPercent() > 50)
        if (ai->CastSpell(LIFE_TAP, *m_bot))
            return;

    if (ai->GetManaPercent() < 25)
    {
        Item* pItem = ai->FindDrink();
        if (pItem)
        {
            ai->TellMaster("I could use a drink.");
            ai->UseItem(pItem);
            return;
        }
    }

    // hp check
    if (ai->GetHealthPercent() < 30)
    {
        Item* pItem = ai->FindFood();
        if (pItem)
        {
            ai->TellMaster("I could use some food.");
            ai->UseItem(pItem);
            return;
        }
    }

    if (ai->GetHealthPercent() < 50 && !m_bot->HasAura(RECENTLY_BANDAGED))
    {
        Item* fItem = ai->FindBandage();
        if (fItem)
        {
            ai->TellMaster("I could use first aid.");
            ai->UseItem(fItem);
            return;
        }
    }

    //Heal Voidwalker
    if (pet && pet->GetEntry() == DEMON_VOIDWALKER && CONSUME_SHADOWS && pet->GetHealthPercent() < 75 && !pet->HasAura(CONSUME_SHADOWS))
        ai->CastPetSpell(CONSUME_SHADOWS);

    // Summon demon
    if (!pet || m_isTempImp)
    {
        uint32 summonSpellId;
        if (m_demonOfChoice != DEMON_IMP && shardCount > 0)
        {
            switch (m_demonOfChoice)
            {
                case DEMON_VOIDWALKER:
                    summonSpellId = SUMMON_VOIDWALKER;
                    break;
                case DEMON_FELGUARD:
                    summonSpellId = SUMMON_FELGUARD;
                    break;
                case DEMON_FELHUNTER:
                    summonSpellId = SUMMON_FELHUNTER;
                    break;
                case DEMON_SUCCUBUS:
                    summonSpellId = SUMMON_SUCCUBUS;
                    break;
                default:
                    summonSpellId = 0;
            }
            if (ai->CastSpell(summonSpellId))
            {
                ai->TellMaster("Summoning favorite demon...");
                m_isTempImp = false;
                return;
            }
        }
        else if (!pet && SUMMON_IMP && ai->CastSpell(SUMMON_IMP))
        {
            if (m_demonOfChoice != DEMON_IMP)
                m_isTempImp = true;

            ai->TellMaster("Summoning Imp...");
            return;
        }
    }

    // Soul link demon
    if (pet && SOUL_LINK && !m_bot->HasAura(SOUL_LINK_AURA) && ai->CastSpell(SOUL_LINK, *m_bot))
        return;

    // Check demon buffs
    if (pet && pet->GetEntry() == DEMON_IMP && BLOOD_PACT && !m_bot->HasAura(BLOOD_PACT) && ai->CastPetSpell(BLOOD_PACT))
        return;

    if (pet && pet->GetEntry() == DEMON_FELHUNTER && FEL_INTELLIGENCE && !m_bot->HasAura(FEL_INTELLIGENCE) && ai->CastPetSpell(FEL_INTELLIGENCE))
        return;

} // end DoNonCombatActions
void PlayerbotWarlockAI::DoNonCombatActions()
{
    if (!m_ai)  return;
    if (!m_bot) return;

    //uint32 spec = m_bot->GetSpec();
    Pet *pet = m_bot->GetPet();

    // Initialize pet spells
    if (pet && pet->GetEntry() != m_lastDemon)
    {
        switch (pet->GetEntry())
        {
            case DEMON_IMP:
                BLOOD_PACT       = m_ai->initPetSpell(BLOOD_PACT_ICON);
                FIREBOLT         = m_ai->initPetSpell(FIREBOLT_ICON);
                FIRE_SHIELD      = m_ai->initPetSpell(FIRE_SHIELD_ICON);
                break;

            case DEMON_VOIDWALKER:
                CONSUME_SHADOWS  = m_ai->initPetSpell(CONSUME_SHADOWS_ICON);
                SACRIFICE        = m_ai->initPetSpell(SACRIFICE_ICON);
                SUFFERING        = m_ai->initPetSpell(SUFFERING_ICON);
                TORMENT          = m_ai->initPetSpell(TORMENT_ICON);
                break;

            case DEMON_SUCCUBUS:
                LASH_OF_PAIN     = m_ai->initPetSpell(LASH_OF_PAIN_ICON);
                SEDUCTION        = m_ai->initPetSpell(SEDUCTION_ICON);
                SOOTHING_KISS    = m_ai->initPetSpell(SOOTHING_KISS_ICON);
                break;

            case DEMON_FELHUNTER:
                DEVOUR_MAGIC     = m_ai->initPetSpell(DEVOUR_MAGIC_ICON);
                SPELL_LOCK       = m_ai->initPetSpell(SPELL_LOCK_ICON);
                break;
        }

        m_lastDemon = pet->GetEntry();
    }

    // Destroy extra soul shards
    uint8 shardCount = m_bot->GetItemCount(SOUL_SHARD, false, nullptr);
    uint8 freeSpace = m_ai->GetFreeBagSpace();
    if (shardCount > MAX_SHARD_COUNT || (freeSpace == 0 && shardCount > 1))
        m_bot->DestroyItemCount(SOUL_SHARD, shardCount > MAX_SHARD_COUNT ? shardCount - MAX_SHARD_COUNT : 1, true, false);

    // buff myself DEMON_SKIN, DEMON_ARMOR, FEL_ARMOR - Strongest one available is chosen
    if (DEMON_ARMOR)
    {
        if (m_ai->SelfBuff(DEMON_ARMOR))
            return;
    }
    else if (DEMON_SKIN)
        if (m_ai->SelfBuff(DEMON_SKIN))
            return;

    // healthstone creation
    if (CREATE_HEALTHSTONE && shardCount > 0)
    {
        Item* const healthStone = m_ai->FindConsumable(HEALTHSTONE_DISPLAYID);
        if (!healthStone && m_ai->CastSpell(CREATE_HEALTHSTONE))
            return;
    }

    // soulstone creation and use
    if (CREATE_SOULSTONE)
    {
        Item* soulStone = m_ai->FindConsumable(SOULSTONE_DISPLAYID);
        if (!soulStone)
        {
            if (shardCount > 0 && m_bot->IsSpellReady(CREATE_SOULSTONE) && m_ai->CastSpell(CREATE_SOULSTONE))
                return;
        }
        else
        {
            uint32 soulStoneSpell = soulStone->GetProto()->Spells[0].SpellId;
            Player* master = GetMaster();
            if (!master->HasAura(soulStoneSpell) && m_bot->IsSpellReady(soulStoneSpell))
            {
                // TODO: first choice: healer. Second choice: anyone else with revive spell. Third choice: self or master.
                m_ai->UseItem(soulStone, master);
                return;
            }
        }
    }

    // hp/mana check
    if (pet && DARK_PACT && (100 * pet->GetPower(POWER_MANA) / pet->GetMaxPower(POWER_MANA)) > 40 && m_ai->GetManaPercent() <= 60)
        if (m_ai->CastSpell(DARK_PACT, *m_bot))
            return;

    if (LIFE_TAP && m_ai->GetManaPercent() <= 80 && m_ai->GetHealthPercent() > 50)
        if (m_ai->CastSpell(LIFE_TAP, *m_bot))
            return;

    // Do not waste time/soul shards to create spellstone or firestone
    // if two-handed weapon (staff) or off-hand item are already equiped
    // Spellstone creation and use (Spellstone dominates firestone completely as I understand it)
    Item* const weapon = m_bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
    Item* const offweapon = m_bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
    if (weapon && !offweapon && weapon->GetProto()->SubClass != ITEM_SUBCLASS_WEAPON_STAFF && weapon->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT) == 0)
    {
        Item* const stone = m_ai->FindConsumable(SPELLSTONE_DISPLAYID);
        Item* const stone2 = m_ai->FindConsumable(FIRESTONE_DISPLAYID);
        uint8 spellstone_count = m_bot->GetItemCount(SPELLSTONE, false, nullptr);
        if (spellstone_count == 0)
            spellstone_count = m_bot->GetItemCount(GREATER_SPELLSTONE, false, nullptr);
        if (spellstone_count == 0)
            spellstone_count = m_bot->GetItemCount(MAJOR_SPELLSTONE, false, nullptr);
        uint8 firestone_count = m_bot->GetItemCount(LESSER_FIRESTONE, false, nullptr);
        if (firestone_count == 0)
            firestone_count = m_bot->GetItemCount(FIRESTONE, false, nullptr);
        if (firestone_count == 0)
            firestone_count = m_bot->GetItemCount(GREATER_FIRESTONE, false, nullptr);
        if (firestone_count == 0)
            firestone_count = m_bot->GetItemCount(MAJOR_FIRESTONE, false, nullptr);
        if (spellstone_count == 0 && firestone_count == 0)
        {
            if (CREATE_SPELLSTONE && shardCount > 0 && m_ai->CastSpell(CREATE_SPELLSTONE))
                return;
            else if (CREATE_SPELLSTONE == 0 && CREATE_FIRESTONE > 0 && shardCount > 0 && m_ai->CastSpell(CREATE_FIRESTONE))
                return;
        }
        else if (stone)
        {
            m_ai->UseItem(stone, EQUIPMENT_SLOT_OFFHAND);
            return;
        }
        else
        {
            m_ai->UseItem(stone2, EQUIPMENT_SLOT_OFFHAND);
            return;
        }
    }

    if (EatDrinkBandage())
        return;

    //Heal Voidwalker
    if (pet && pet->GetEntry() == DEMON_VOIDWALKER && CONSUME_SHADOWS && pet->GetHealthPercent() < 75 && !pet->HasAura(CONSUME_SHADOWS))
        m_ai->CastPetSpell(CONSUME_SHADOWS);

    CheckDemon();

    // Soul link demon
    if (pet && SOUL_LINK && !m_bot->HasAura(SOUL_LINK_AURA) && m_ai->CastSpell(SOUL_LINK, *m_bot))
        return;

    // Check demon buffs
    if (pet && pet->GetEntry() == DEMON_IMP && BLOOD_PACT && !m_bot->HasAura(BLOOD_PACT) && m_ai->CastPetSpell(BLOOD_PACT))
        return;
} // end DoNonCombatActions
CombatManeuverReturns PlayerbotWarlockAI::DoNextCombatManeuverPVE(Unit *pTarget)
{
    if (!m_ai)  return RETURN_NO_ACTION_ERROR;
    if (!m_bot) return RETURN_NO_ACTION_ERROR;

    //Unit* pVictim = pTarget->getVictim();
    bool meleeReach = m_bot->CanReachWithMeleeAttack(pTarget);
    Pet *pet = m_bot->GetPet();
    uint32 spec = m_bot->GetSpec();
    uint8 shardCount = m_bot->GetItemCount(SOUL_SHARD, false, nullptr);

    // Voidwalker is near death - sacrifice it for a shield
    if (pet && pet->GetEntry() == DEMON_VOIDWALKER && SACRIFICE && !m_bot->HasAura(SACRIFICE) && pet->GetHealthPercent() < 10)
        m_ai->CastPetSpell(SACRIFICE);

    // Use healthstone
    if (m_ai->GetHealthPercent() < 30)
    {
        Item* healthStone = m_ai->FindConsumable(HEALTHSTONE_DISPLAYID);
        if (healthStone)
            m_ai->UseItem(healthStone);
    }

    // Voidwalker sacrifice gives shield - but you lose the pet (and it's DPS/tank) - use only as last resort for your own health!
    if (m_ai->GetHealthPercent() < 20 && pet && pet->GetEntry() == DEMON_VOIDWALKER && SACRIFICE && !m_bot->HasAura(SACRIFICE))
        m_ai->CastPetSpell(SACRIFICE);

    if (m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_RANGED && !meleeReach)
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_RANGED);
    // switch to melee if in melee range AND can't shoot OR have no ranged (wand) equipped
    else if(m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_MELEE
            && meleeReach
            && (SHOOT == 0 || !m_bot->GetWeaponForAttack(RANGED_ATTACK, true, true)))
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_MELEE);

    //Used to determine if this bot is highest on threat
    Unit *newTarget = m_ai->FindAttacker((PlayerbotAI::ATTACKERINFOTYPE) (PlayerbotAI::AIT_VICTIMSELF | PlayerbotAI::AIT_HIGHESTTHREAT), m_bot);
    if (newTarget && !m_ai->IsNeutralized(newTarget)) // TODO: && party has a tank
    {
        // Have threat, can't quickly lower it. 3 options remain: Stop attacking, lowlevel damage (wand), keep on keeping on.
        if (newTarget->GetHealthPercent() > 25)
        {
            // If elite
            if (m_ai->IsElite(newTarget))
            {
                // let warlock pet handle it to win some time
                Creature * pCreature = (Creature*) newTarget;
                if (pet)
                {
                    switch (pet->GetEntry())
                    {
                        // taunt the elite and tank it
                        case DEMON_VOIDWALKER:
                            if (TORMENT && m_ai->CastPetSpell(TORMENT, newTarget))
                                return RETURN_NO_ACTION_OK;
                        // maybe give it some love?
                        case DEMON_SUCCUBUS:
                            if (pCreature && pCreature->GetCreatureInfo()->CreatureType == CREATURE_TYPE_HUMANOID)
                                if (SEDUCTION && !newTarget->HasAura(SEDUCTION) && m_ai->CastPetSpell(SEDUCTION, newTarget))
                                    return RETURN_NO_ACTION_OK;
                    }

                }
                // if aggroed mob is a demon or an elemental: banish it
                if (pCreature && (pCreature->GetCreatureInfo()->CreatureType == CREATURE_TYPE_DEMON || pCreature->GetCreatureInfo()->CreatureType == CREATURE_TYPE_ELEMENTAL))
                {
                    if (BANISH && !newTarget->HasAura(BANISH) && CastSpell(BANISH, newTarget))
                        return RETURN_CONTINUE;
                }

                return RETURN_NO_ACTION_OK; // do nothing and pray tank gets aggro off you
            }

            // Not an elite. You could insert FEAR here but in any PvE situation that's 90-95% likely
            // to worsen the situation for the group. ... So please don't.
            return CastSpell(SHOOT, pTarget);
        }
    }

    // Create soul shard (only on non-worldboss)
    uint8 freeSpace = m_ai->GetFreeBagSpace();
    uint8 HPThreshold = (m_ai->IsElite(pTarget) ? 10 : 25);
    if (!m_ai->IsElite(pTarget, true) && pTarget->GetHealthPercent() < HPThreshold && (shardCount < MAX_SHARD_COUNT && freeSpace > 0))
    {
        if (SHADOWBURN && m_ai->In_Reach(pTarget, SHADOWBURN) && !pTarget->HasAura(SHADOWBURN) && m_bot->IsSpellReady(SHADOWBURN) && CastSpell(SHADOWBURN, pTarget))
            return RETURN_CONTINUE;

        // Do not cast Drain Soul if Shadowburn is active on target
        if (DRAIN_SOUL && m_ai->In_Reach(pTarget, DRAIN_SOUL) && !pTarget->HasAura(DRAIN_SOUL) && !pTarget->HasAura(SHADOWBURN) && CastSpell(DRAIN_SOUL, pTarget))
        {
            m_ai->SetIgnoreUpdateTime(15);
            return RETURN_CONTINUE;
        }
    }

    if (pet && DARK_PACT && (100 * pet->GetPower(POWER_MANA) / pet->GetMaxPower(POWER_MANA)) > 10 && m_ai->GetManaPercent() <= 20)
        if (m_ai->CastSpell(DARK_PACT, *m_bot))
            return RETURN_CONTINUE;

    // Mana check and replenishment
    if (LIFE_TAP && m_ai->GetManaPercent() <= 20 && m_ai->GetHealthPercent() > 50)
        if (m_ai->CastSpell(LIFE_TAP, *m_bot))
            return RETURN_CONTINUE;

    // HP, mana and aggro checks done
    // Curse the target
    if (CheckCurse(pTarget))
        return RETURN_CONTINUE;

    // Damage Spells
    if (spec)
    {
        switch (spec)
        {
            case WARLOCK_SPEC_AFFLICTION:
                if (CORRUPTION && m_ai->In_Reach(pTarget,CORRUPTION) && !pTarget->HasAura(CORRUPTION) && CastSpell(CORRUPTION, pTarget))
                    return RETURN_CONTINUE;
                if (IMMOLATE && m_ai->In_Reach(pTarget,IMMOLATE) && !pTarget->HasAura(IMMOLATE) && CastSpell(IMMOLATE, pTarget))
                    return RETURN_CONTINUE;
                if (SIPHON_LIFE > 0 && m_ai->In_Reach(pTarget,SIPHON_LIFE) && !pTarget->HasAura(SIPHON_LIFE) && CastSpell(SIPHON_LIFE, pTarget))
                    return RETURN_CONTINUE;
                break;

            case WARLOCK_SPEC_DEMONOLOGY:
                if (CORRUPTION && m_ai->In_Reach(pTarget,CORRUPTION) && !pTarget->HasAura(CORRUPTION) && CastSpell(CORRUPTION, pTarget))
                    return RETURN_CONTINUE;
                if (IMMOLATE && m_ai->In_Reach(pTarget,IMMOLATE) && !pTarget->HasAura(IMMOLATE) && CastSpell(IMMOLATE, pTarget))
                    return RETURN_CONTINUE;
                break;

            case WARLOCK_SPEC_DESTRUCTION:
                if (SHADOWBURN && pTarget->GetHealthPercent() < (HPThreshold / 2.0) && m_ai->In_Reach(pTarget, SHADOWBURN) && !pTarget->HasAura(SHADOWBURN) && CastSpell(SHADOWBURN, pTarget))
                    return RETURN_CONTINUE;
                if (CORRUPTION && m_ai->In_Reach(pTarget,CORRUPTION) && !pTarget->HasAura(CORRUPTION) && CastSpell(CORRUPTION, pTarget))
                    return RETURN_CONTINUE;
                if (IMMOLATE && m_ai->In_Reach(pTarget,IMMOLATE) && !pTarget->HasAura(IMMOLATE) && CastSpell(IMMOLATE, pTarget))
                    return RETURN_CONTINUE;
                if (CONFLAGRATE && m_ai->In_Reach(pTarget,CONFLAGRATE) && pTarget->HasAura(IMMOLATE) && m_bot->IsSpellReady(CONFLAGRATE) && CastSpell(CONFLAGRATE, pTarget))
                    return RETURN_CONTINUE;
                break;
        }

        // Shadow bolt is common to all specs
        if (SHADOW_BOLT && m_ai->In_Reach(pTarget,SHADOW_BOLT) && CastSpell(SHADOW_BOLT, pTarget))
            return RETURN_CONTINUE;

        // Default: shoot with wand
        return CastSpell(SHOOT, pTarget);

        return RETURN_NO_ACTION_OK;

                //if (DRAIN_LIFE && LastSpellAffliction < 4 && !pTarget->HasAura(DRAIN_SOUL) && !pTarget->HasAura(DRAIN_LIFE) && !pTarget->HasAura(DRAIN_MANA) && m_ai->GetHealthPercent() <= 70)
                //    m_ai->CastSpell(DRAIN_LIFE, *pTarget);
                //    //m_ai->SetIgnoreUpdateTime(5);
                //else if (HOWL_OF_TERROR && !pTarget->HasAura(HOWL_OF_TERROR) && m_ai->GetAttackerCount() > 3 && LastSpellAffliction < 8)
                //    m_ai->CastSpell(HOWL_OF_TERROR, *pTarget);
                //    m_ai->TellMaster("casting howl of terror!");
                //else if (FEAR && !pTarget->HasAura(FEAR) && pVictim == m_bot && m_ai->GetAttackerCount() >= 2 && LastSpellAffliction < 9)
                //    m_ai->CastSpell(FEAR, *pTarget);
                //    //m_ai->TellMaster("casting fear!");
                //    //m_ai->SetIgnoreUpdateTime(1.5);
                //else if (RAIN_OF_FIRE && LastSpellDestruction < 3 && m_ai->GetAttackerCount() >= 3)
                //    m_ai->CastSpell(RAIN_OF_FIRE, *pTarget);
                //    //m_ai->TellMaster("casting rain of fire!");
                //    //m_ai->SetIgnoreUpdateTime(8);
                //else if (SEARING_PAIN && LastSpellDestruction < 8)
                //    m_ai->CastSpell(SEARING_PAIN, *pTarget);
                //else if (SOUL_FIRE && LastSpellDestruction < 9)
                //    m_ai->CastSpell(SOUL_FIRE, *pTarget);
                //    //m_ai->SetIgnoreUpdateTime(6);
                //else if (HELLFIRE && LastSpellDestruction < 12 && !m_bot->HasAura(HELLFIRE) && m_ai->GetAttackerCount() >= 5 && m_ai->GetHealthPercent() >= 50)
                //    m_ai->CastSpell(HELLFIRE);
                //    m_ai->TellMaster("casting hellfire!");
                //    //m_ai->SetIgnoreUpdateTime(15);
    }

    // No spec due to low level OR no spell found yet
    if (CORRUPTION && m_ai->In_Reach(pTarget,CORRUPTION) && !pTarget->HasAura(CORRUPTION) && CastSpell(CORRUPTION, pTarget))
        return RETURN_CONTINUE;
    if (IMMOLATE && m_ai->In_Reach(pTarget,IMMOLATE) && !pTarget->HasAura(IMMOLATE) && CastSpell(IMMOLATE, pTarget))
        return RETURN_CONTINUE;
    if (SHADOW_BOLT && m_ai->In_Reach(pTarget,SHADOW_BOLT))
        return CastSpell(SHADOW_BOLT, pTarget);

    // Default: shoot with wand
    return CastSpell(SHOOT, pTarget);

    return RETURN_NO_ACTION_OK;
} // end DoNextCombatManeuver
void PlayerbotHunterAI::DoNonCombatActions()
{
    if (!m_ai)  return;
    if (!m_bot) return;

    if (!m_rangedCombat || m_ai->GetCombatStyle() == PlayerbotAI::COMBAT_MELEE)
    {
        m_rangedCombat = true;
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_RANGED);
    }

    // buff group
    if (TRUESHOT_AURA > 0 && !m_bot->HasAura(TRUESHOT_AURA, EFFECT_INDEX_0))
        m_ai->CastSpell(TRUESHOT_AURA, *m_bot);

    // buff myself
    if (ASPECT_OF_THE_HAWK > 0 && !m_bot->HasAura(ASPECT_OF_THE_HAWK, EFFECT_INDEX_0))
        m_ai->CastSpell(ASPECT_OF_THE_HAWK, *m_bot);

	//create water
	if (m_ai->FindDrink() == nullptr && m_bot->getLevel() == 60)
	{
		if (Item* pItem = m_bot->StoreNewItemInInventorySlot(CRYSTAL_WATER, 20))
			m_bot->SendNewItem(pItem, 20, true, false);
		
		return;
	}

    // hp/mana check
    if (EatDrinkBandage())
        return;

    // check for pet
    if (PET_SUMMON > 0 && !m_petSummonFailed && HasPet(m_bot))
    {
        // we can summon pet, and no critical summon errors before
        Pet *pet = m_bot->GetPet();
        if (!pet)
        {
            // summon pet
            if (PET_SUMMON > 0 && m_ai->CastSpell(PET_SUMMON, *m_bot))
                m_ai->TellMaster("summoning pet.");
            else
            {
                m_petSummonFailed = true;
                m_ai->TellMaster("summon pet failed!");
            }
        }
        else if (!(pet->isAlive()))
        {
            if (PET_REVIVE > 0 && m_ai->CastSpell(PET_REVIVE, *m_bot))
                m_ai->TellMaster("reviving pet.");
        }
        else if (pet->GetHealthPercent() < 50)
        {
            if (PET_MEND > 0 && pet->isAlive() && !pet->HasAura(PET_MEND, EFFECT_INDEX_0) && m_ai->CastSpell(PET_MEND, *m_bot))
                m_ai->TellMaster("healing pet.");
        }
        else if (pet->GetHappinessState() != HAPPY) // if pet is hungry
        {
            Unit *caster = (Unit *) m_bot;
            // list out items in main backpack
            for (uint8 slot = INVENTORY_SLOT_ITEM_START; slot < INVENTORY_SLOT_ITEM_END; slot++)
            {
                Item* const pItem = m_bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot);
                if (pItem)
                {
                    const ItemPrototype* const pItemProto = pItem->GetProto();
                    if (!pItemProto)
                        continue;

                    if (pet->HaveInDiet(pItemProto)) // is pItem in pets diet
                    {
                        // DEBUG_LOG ("[PlayerbotHunterAI]: DoNonCombatActions - Food for pet: %s",pItemProto->Name1);
                        caster->CastSpell(caster, 23355, true); // pet feed visual
                        uint32 count = 1; // number of items used
                        int32 benefit = pet->GetCurrentFoodBenefitLevel(pItemProto->ItemLevel); // nutritional value of food
                        m_bot->DestroyItemCount(pItem, count, true); // remove item from inventory
                        m_bot->CastCustomSpell(m_bot, PET_FEED, &benefit, nullptr, nullptr, true); // feed pet
                        m_ai->TellMaster("feeding pet.");
                        m_ai->SetIgnoreUpdateTime(10);
                        return;
                    }
                }
            }
            // list out items in other removable backpacks
            for (uint8 bag = INVENTORY_SLOT_BAG_START; bag < INVENTORY_SLOT_BAG_END; ++bag)
            {
                const Bag* const pBag = (Bag *) m_bot->GetItemByPos(INVENTORY_SLOT_BAG_0, bag);
                if (pBag)
                    for (uint8 slot = 0; slot < pBag->GetBagSize(); ++slot)
                    {
                        Item* const pItem = m_bot->GetItemByPos(bag, slot);
                        if (pItem)
                        {
                            const ItemPrototype* const pItemProto = pItem->GetProto();
                            if (!pItemProto)
                                continue;

                            if (pet->HaveInDiet(pItemProto)) // is pItem in pets diet
                            {
                                // DEBUG_LOG ("[PlayerbotHunterAI]: DoNonCombatActions - Food for pet: %s",pItemProto->Name1);
                                caster->CastSpell(caster, 23355, true); // pet feed visual
                                uint32 count = 1; // number of items used
                                int32 benefit = pet->GetCurrentFoodBenefitLevel(pItemProto->ItemLevel); // nutritional value of food
                                m_bot->DestroyItemCount(pItem, count, true); // remove item from inventory
                                m_bot->CastCustomSpell(m_bot, PET_FEED, &benefit, nullptr, nullptr, true); // feed pet
                                m_ai->TellMaster("feeding pet.");
                                m_ai->SetIgnoreUpdateTime(10);
                                return;
                            }
                        }
                    }
            }
            if (pet->HasAura(PET_MEND, EFFECT_INDEX_0) && !pet->HasAura(PET_FEED, EFFECT_INDEX_0))
                m_ai->TellMaster("..no pet food!");
            m_ai->SetIgnoreUpdateTime(7);
        }
    }
} // end DoNonCombatActions
CombatManeuverReturns PlayerbotHunterAI::DoNextCombatManeuverPVE(Unit *pTarget)
{
    if (!m_ai)    return RETURN_NO_ACTION_ERROR;
    if (!m_bot)   return RETURN_NO_ACTION_ERROR;
    if (!pTarget) return RETURN_NO_ACTION_ERROR;

    Unit* pVictim = pTarget->getVictim();

    // check for pet and heal if neccessary
    Pet *pet = m_bot->GetPet();
    // TODO: clarify/simplify: !pet->getDeathState() != ALIVE
    if (pet && PET_MEND > 0 && pet->isAlive() && pet->GetHealthPercent() < 50 && pVictim != m_bot && !pet->HasAura(PET_MEND, EFFECT_INDEX_0) && m_ai->CastSpell(PET_MEND, *m_bot))
    {
        m_ai->TellMaster("healing pet.");
        return RETURN_CONTINUE;
    }
    else if (pet && INTIMIDATION > 0 && pVictim == pet && !pet->HasAura(INTIMIDATION, EFFECT_INDEX_0) && m_ai->CastSpell(INTIMIDATION, *m_bot))
        return RETURN_CONTINUE;

    // racial traits
    if (m_bot->getRace() == RACE_ORC && !m_bot->HasAura(BLOOD_FURY, EFFECT_INDEX_0))
        m_ai->CastSpell(BLOOD_FURY, *m_bot);
    else if (m_bot->getRace() == RACE_TROLL && !m_bot->HasAura(BERSERKING, EFFECT_INDEX_0))
        m_ai->CastSpell(BERSERKING, *m_bot);

    // check if ranged combat is possible
    bool meleeReach = m_bot->CanReachWithMeleeAttack(pTarget);

    if (meleeReach || !m_has_ammo)
    {
        // switch to melee combat (target in melee range, out of ammo)
        m_rangedCombat = false;
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_MELEE);
        if (!m_bot->GetUInt32Value(PLAYER_AMMO_ID))
            m_ai->TellMaster("Out of ammo!");

        // become monkey (increases dodge chance)...
        if (ASPECT_OF_THE_MONKEY > 0 && !m_bot->HasAura(ASPECT_OF_THE_MONKEY, EFFECT_INDEX_0))
            m_ai->CastSpell(ASPECT_OF_THE_MONKEY, *m_bot);

    }
    else if (!meleeReach)
    {
        // switch to ranged combat
        m_rangedCombat = true;
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_RANGED);

        // increase ranged attack power...
        if (ASPECT_OF_THE_HAWK > 0 && !m_bot->HasAura(ASPECT_OF_THE_HAWK, EFFECT_INDEX_0))
            m_ai->CastSpell(ASPECT_OF_THE_HAWK, *m_bot);

        // m_ai->TellMaster("target dist %f",m_bot->GetCombatDistance(pTarget,true));
        if (AUTO_SHOT > 0)
        {
            if (m_bot->isAttackReady(RANGED_ATTACK))
                m_bot->CastSpell(pTarget, AUTO_SHOT, true);

            m_bot->setAttackTimer(RANGED_ATTACK,500);

            const SpellEntry* spellInfo = sSpellStore.LookupEntry(AUTO_SHOT);
            if (!spellInfo)
                return RETURN_CONTINUE;

            if (m_ai->CheckBotCast(spellInfo) != SPELL_CAST_OK)
                m_bot->InterruptNonMeleeSpells(true, AUTO_SHOT);
        }
    }

    // damage spells
    if (m_ai->GetCombatStyle() == PlayerbotAI::COMBAT_RANGED)
    {
        if (HUNTERS_MARK > 0 && m_ai->In_Reach(pTarget,HUNTERS_MARK) && !pTarget->HasAura(HUNTERS_MARK, EFFECT_INDEX_0) && m_ai->CastSpell(HUNTERS_MARK, *pTarget))
            return RETURN_CONTINUE;
        else if (RAPID_FIRE > 0 && m_ai->In_Reach(pTarget,RAPID_FIRE) && !m_bot->HasAura(RAPID_FIRE, EFFECT_INDEX_0) && m_ai->CastSpell(RAPID_FIRE, *m_bot))
            return RETURN_CONTINUE;
        else if (MULTI_SHOT > 0 && m_ai->In_Reach(pTarget,MULTI_SHOT) && m_ai->GetAttackerCount() >= 3 && m_ai->CastSpell(MULTI_SHOT, *pTarget))
            return RETURN_CONTINUE;
        else if (ARCANE_SHOT > 0 && m_ai->In_Reach(pTarget,ARCANE_SHOT) && m_ai->CastSpell(ARCANE_SHOT, *pTarget))
            return RETURN_CONTINUE;
        else if (CONCUSSIVE_SHOT > 0 && m_ai->In_Reach(pTarget,CONCUSSIVE_SHOT) && !pTarget->HasAura(CONCUSSIVE_SHOT, EFFECT_INDEX_0) && m_ai->CastSpell(CONCUSSIVE_SHOT, *pTarget))
            return RETURN_CONTINUE;
        else if (VIPER_STING > 0 && m_ai->In_Reach(pTarget,VIPER_STING) && pTarget->GetPower(POWER_MANA) > 0 && m_ai->GetManaPercent() < 70 && !pTarget->HasAura(VIPER_STING, EFFECT_INDEX_0) && m_ai->CastSpell(VIPER_STING, *pTarget))
            return RETURN_CONTINUE;
        else if (SERPENT_STING > 0 && m_ai->In_Reach(pTarget,SERPENT_STING) && !pTarget->HasAura(SERPENT_STING, EFFECT_INDEX_0) && !pTarget->HasAura(SCORPID_STING, EFFECT_INDEX_0) &&  !pTarget->HasAura(VIPER_STING, EFFECT_INDEX_0) && m_ai->CastSpell(SERPENT_STING, *pTarget))
            return RETURN_CONTINUE;
        else if (SCORPID_STING > 0 && m_ai->In_Reach(pTarget,SCORPID_STING) && !pTarget->HasAura(WYVERN_STING, EFFECT_INDEX_0) && !pTarget->HasAura(SCORPID_STING, EFFECT_INDEX_0) && !pTarget->HasAura(SERPENT_STING, EFFECT_INDEX_0) && !pTarget->HasAura(VIPER_STING, EFFECT_INDEX_0) && m_ai->CastSpell(SCORPID_STING, *pTarget))
            return RETURN_CONTINUE;
        else if (VOLLEY > 0 && m_ai->In_Reach(pTarget,VOLLEY) && m_ai->GetAttackerCount() >= 3 && m_ai->CastSpell(VOLLEY, *pTarget))
            return RETURN_CONTINUE;
        else if (BLACK_ARROW > 0 && m_ai->In_Reach(pTarget,BLACK_ARROW) && !pTarget->HasAura(BLACK_ARROW, EFFECT_INDEX_0) && m_ai->CastSpell(BLACK_ARROW, *pTarget))
            return RETURN_CONTINUE;
        else if (AIMED_SHOT > 0 && m_ai->In_Reach(pTarget,AIMED_SHOT) && m_ai->CastSpell(AIMED_SHOT, *pTarget))
            return RETURN_CONTINUE;
        else
            return RETURN_NO_ACTION_OK;
    }
    else
    {
        if (RAPTOR_STRIKE > 0 && m_ai->In_Reach(pTarget,RAPTOR_STRIKE) && m_ai->CastSpell(RAPTOR_STRIKE, *pTarget))
            return RETURN_CONTINUE;
        else if (EXPLOSIVE_TRAP > 0 && !pTarget->HasAura(EXPLOSIVE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(IMMOLATION_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(FROST_TRAP, EFFECT_INDEX_0) && m_ai->CastSpell(EXPLOSIVE_TRAP, *pTarget))
            return RETURN_CONTINUE;
        else if (WING_CLIP > 0 && m_ai->In_Reach(pTarget,WING_CLIP) && !pTarget->HasAura(WING_CLIP, EFFECT_INDEX_0) && m_ai->CastSpell(WING_CLIP, *pTarget))
            return RETURN_CONTINUE;
        else if (IMMOLATION_TRAP > 0 && !pTarget->HasAura(IMMOLATION_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(EXPLOSIVE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(FROST_TRAP, EFFECT_INDEX_0) && m_ai->CastSpell(IMMOLATION_TRAP, *pTarget))
            return RETURN_CONTINUE;
        else if (MONGOOSE_BITE > 0 && m_ai->Impulse() && m_ai->CastSpell(MONGOOSE_BITE, *pTarget))
            return RETURN_CONTINUE;
        else if (FROST_TRAP > 0 && !pTarget->HasAura(FROST_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(IMMOLATION_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(EXPLOSIVE_TRAP, EFFECT_INDEX_0) && m_ai->CastSpell(FROST_TRAP, *pTarget))
            return RETURN_CONTINUE;
        else if (DETERRENCE > 0 && pVictim == m_bot && m_bot->GetHealthPercent() < 50 && !m_bot->HasAura(DETERRENCE, EFFECT_INDEX_0) && m_ai->CastSpell(DETERRENCE, *m_bot))
            return RETURN_CONTINUE;
        else if (m_bot->getRace() == RACE_TAUREN && !pTarget->HasAura(WAR_STOMP, EFFECT_INDEX_0) && m_ai->CastSpell(WAR_STOMP, *pTarget))
            return RETURN_CONTINUE;
//        else if (m_bot->getRace() == RACE_DWARF && m_bot->HasAuraState(AURA_STATE_DEADLY_POISON) && m_ai->CastSpell(STONEFORM, *m_bot))
//            return RETURN_CONTINUE;
        else if (m_bot->getRace() == RACE_NIGHTELF && pVictim == m_bot && m_ai->GetHealthPercent() < 25 && !m_bot->HasAura(SHADOWMELD, EFFECT_INDEX_0) && m_ai->CastSpell(SHADOWMELD, *m_bot))
            return RETURN_CONTINUE;

        /*else if(FREEZING_TRAP > 0 && !pTarget->HasAura(FREEZING_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(ARCANE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(EXPLOSIVE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(BEAR_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(IMMOLATION_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(FROST_TRAP, EFFECT_INDEX_0) && m_ai->CastSpell(FREEZING_TRAP,*pTarget) )
            out << " > Freezing Trap"; // this can trap your bots too
           else if(DISENGAGE > 0 && pVictim && m_ai->CastSpell(DISENGAGE,*pTarget) )
            out << " > Disengage!"; // attempt to return to ranged combat*/
    }

    return RETURN_NO_ACTION_OK;
} // end DoNextCombatManeuver
CombatManeuverReturns PlayerbotWarlockAI::DoNextCombatManeuverPVE(Unit *pTarget)
{
    if (!m_ai)  return RETURN_NO_ACTION_ERROR;
    if (!m_bot) return RETURN_NO_ACTION_ERROR;

    //Unit* pVictim = pTarget->getVictim();
    bool meleeReach = m_bot->CanReachWithMeleeAttack(pTarget);
    Pet *pet = m_bot->GetPet();
    uint32 spec = m_bot->GetSpec();
    uint8 shardCount = m_bot->GetItemCount(SOUL_SHARD, false, nullptr);

    //If we have UA it will replace immolate in our rotation
    uint32 FIRE = (UNSTABLE_AFFLICTION > 0 ? UNSTABLE_AFFLICTION : IMMOLATE);

    // Voidwalker is near death - sacrifice it for a shield
    if (pet && pet->GetEntry() == DEMON_VOIDWALKER && SACRIFICE && !m_bot->HasAura(SACRIFICE) && pet->GetHealthPercent() < 10)
        m_ai->CastPetSpell(SACRIFICE);

    // Use healthstone
    if (m_ai->GetHealthPercent() < 30)
    {
        Item* healthStone = m_ai->FindConsumable(HEALTHSTONE_DISPLAYID);
        if (healthStone)
            m_ai->UseItem(healthStone);
    }

    // Voidwalker sacrifice gives shield - but you lose the pet (and it's DPS/tank) - use only as last resort for your own health!
    if (m_ai->GetHealthPercent() < 20 && pet && pet->GetEntry() == DEMON_VOIDWALKER && SACRIFICE && !m_bot->HasAura(SACRIFICE))
        m_ai->CastPetSpell(SACRIFICE);

    if (m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_RANGED && !meleeReach)
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_RANGED);
    // if in melee range OR can't shoot OR have no ranged (wand) equipped
    else if(m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_MELEE && (meleeReach || SHOOT == 0 || !m_bot->GetWeaponForAttack(RANGED_ATTACK, true, true)))
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_MELEE);

    //Used to determine if this bot is highest on threat
    Unit *newTarget = m_ai->FindAttacker((PlayerbotAI::ATTACKERINFOTYPE) (PlayerbotAI::AIT_VICTIMSELF | PlayerbotAI::AIT_HIGHESTTHREAT), m_bot);
    if (newTarget) // TODO: && party has a tank
    {
        if (SOULSHATTER > 0 && shardCount > 0 && !m_bot->HasSpellCooldown(SOULSHATTER))
            if (CastSpell(SOULSHATTER, m_bot))
                return RETURN_CONTINUE;

        // Have threat, can't quickly lower it. 3 options remain: Stop attacking, lowlevel damage (wand), keep on keeping on.
        if (newTarget->GetHealthPercent() > 25)
        {
            // If elite, do nothing and pray tank gets aggro off you
            // TODO: Is there an IsElite function? If so, find it and insert.
            //if (newTarget->IsElite())
            //    return;

            // Not an elite. You could insert FEAR here but in any PvE situation that's 90-95% likely
            // to worsen the situation for the group. ... So please don't.
            return CastSpell(SHOOT, pTarget);
        }
    }

    // Damage Spells
    switch (spec)
    {
        case WARLOCK_SPEC_AFFLICTION:
            if (CURSE_OF_AGONY && m_ai->In_Reach(pTarget,CURSE_OF_AGONY) && !pTarget->HasAura(CURSE_OF_AGONY) && CastSpell(CURSE_OF_AGONY, pTarget))
                return RETURN_CONTINUE;
            if (CORRUPTION && m_ai->In_Reach(pTarget,CORRUPTION) && !pTarget->HasAura(CORRUPTION) && CastSpell(CORRUPTION, pTarget))
                return RETURN_CONTINUE;
            if (FIRE && m_ai->In_Reach(pTarget,FIRE) && !pTarget->HasAura(FIRE) && CastSpell(FIRE, pTarget))
                return RETURN_CONTINUE;
            if (HAUNT && m_ai->In_Reach(pTarget,HAUNT) && !m_bot->HasSpellCooldown(HAUNT) && CastSpell(HAUNT, pTarget))
                return RETURN_CONTINUE;
            if (SHADOW_BOLT && m_ai->In_Reach(pTarget,SHADOW_BOLT) && CastSpell(SHADOW_BOLT, pTarget))
                return RETURN_CONTINUE;

            return RETURN_NO_ACTION_OK;

        case WARLOCK_SPEC_DEMONOLOGY:
            if (pet && DEMONIC_EMPOWERMENT && !m_bot->HasSpellCooldown(DEMONIC_EMPOWERMENT) && CastSpell(DEMONIC_EMPOWERMENT))
                return RETURN_CONTINUE;
            if (CURSE_OF_AGONY && m_ai->In_Reach(pTarget,CURSE_OF_AGONY) && !pTarget->HasAura(CURSE_OF_AGONY) && CastSpell(CURSE_OF_AGONY, pTarget))
                return RETURN_CONTINUE;
            if (CORRUPTION && m_ai->In_Reach(pTarget,CORRUPTION) && !pTarget->HasAura(CORRUPTION) && CastSpell(CORRUPTION, pTarget))
                return RETURN_CONTINUE;
            if (FIRE && m_ai->In_Reach(pTarget,FIRE) && !pTarget->HasAura(FIRE) && CastSpell(FIRE, pTarget))
                return RETURN_CONTINUE;
            if (INCINERATE && m_ai->In_Reach(pTarget,INCINERATE) && pTarget->HasAura(FIRE) && CastSpell(INCINERATE, pTarget))
                return RETURN_CONTINUE;
            if (SHADOW_BOLT && m_ai->In_Reach(pTarget,SHADOW_BOLT) && CastSpell(SHADOW_BOLT, pTarget))
                return RETURN_CONTINUE;

            return RETURN_NO_ACTION_OK;

        case WARLOCK_SPEC_DESTRUCTION:
            if (CURSE_OF_AGONY && m_ai->In_Reach(pTarget,CURSE_OF_AGONY) && !pTarget->HasAura(CURSE_OF_AGONY) && CastSpell(CURSE_OF_AGONY, pTarget))
                return RETURN_CONTINUE;
            if (CORRUPTION && m_ai->In_Reach(pTarget,CORRUPTION) && !pTarget->HasAura(CORRUPTION) && CastSpell(CORRUPTION, pTarget))
                return RETURN_CONTINUE;
            if (FIRE && m_ai->In_Reach(pTarget,FIRE) && !pTarget->HasAura(FIRE) && CastSpell(FIRE, pTarget))
                return RETURN_CONTINUE;
            if (CONFLAGRATE && m_ai->In_Reach(pTarget,CONFLAGRATE) && pTarget->HasAura(FIRE) && !m_bot->HasSpellCooldown(CONFLAGRATE) && CastSpell(CONFLAGRATE, pTarget))
                return RETURN_CONTINUE;
            if (CHAOS_BOLT && m_ai->In_Reach(pTarget,CHAOS_BOLT) && !m_bot->HasSpellCooldown(CHAOS_BOLT) && CastSpell(CHAOS_BOLT, pTarget))
                return RETURN_CONTINUE;
            if (INCINERATE && m_ai->In_Reach(pTarget,INCINERATE) && pTarget->HasAura(FIRE) && CastSpell(INCINERATE, pTarget))
                return RETURN_CONTINUE;
            if (SHADOW_BOLT && m_ai->In_Reach(pTarget,SHADOW_BOLT) && CastSpell(SHADOW_BOLT, pTarget))
                return RETURN_CONTINUE;

            return RETURN_NO_ACTION_OK;

            //if (LIFE_TAP && LastSpellAffliction < 1 && m_ai->GetManaPercent() <= 50 && m_ai->GetHealthPercent() > 50)
            //    m_ai->CastSpell(LIFE_TAP, *m_bot);
            //else if (DRAIN_SOUL && pTarget->GetHealth() < pTarget->GetMaxHealth() * 0.40 && !pTarget->HasAura(DRAIN_SOUL) && LastSpellAffliction < 3)
            //    m_ai->CastSpell(DRAIN_SOUL, *pTarget);
            //    //m_ai->SetIgnoreUpdateTime(15);
            //else if (DRAIN_LIFE && LastSpellAffliction < 4 && !pTarget->HasAura(DRAIN_SOUL) && !pTarget->HasAura(SEED_OF_CORRUPTION) && !pTarget->HasAura(DRAIN_LIFE) && !pTarget->HasAura(DRAIN_MANA) && m_ai->GetHealthPercent() <= 70)
            //    m_ai->CastSpell(DRAIN_LIFE, *pTarget);
            //    //m_ai->SetIgnoreUpdateTime(5);
            //else if (SEED_OF_CORRUPTION && !pTarget->HasAura(SEED_OF_CORRUPTION) && LastSpellAffliction < 7)
            //    m_ai->CastSpell(SEED_OF_CORRUPTION, *pTarget);
            //else if (HOWL_OF_TERROR && !pTarget->HasAura(HOWL_OF_TERROR) && m_ai->GetAttackerCount() > 3 && LastSpellAffliction < 8)
            //    m_ai->CastSpell(HOWL_OF_TERROR, *pTarget);
            //    m_ai->TellMaster("casting howl of terror!");
            //else if (FEAR && !pTarget->HasAura(FEAR) && pVictim == m_bot && m_ai->GetAttackerCount() >= 2 && LastSpellAffliction < 9)
            //    m_ai->CastSpell(FEAR, *pTarget);
            //    //m_ai->TellMaster("casting fear!");
            //    //m_ai->SetIgnoreUpdateTime(1.5);
            //else if ((pet) && (DARK_PACT > 0 && m_ai->GetManaPercent() <= 50 && LastSpellAffliction < 10 && pet->GetPower(POWER_MANA) > 0))
            //    m_ai->CastSpell(DARK_PACT, *m_bot);
            //if (SHADOWFURY && LastSpellDestruction < 1 && !pTarget->HasAura(SHADOWFURY))
            //    m_ai->CastSpell(SHADOWFURY, *pTarget);
            //else if (RAIN_OF_FIRE && LastSpellDestruction < 3 && m_ai->GetAttackerCount() >= 3)
            //    m_ai->CastSpell(RAIN_OF_FIRE, *pTarget);
            //    //m_ai->TellMaster("casting rain of fire!");
            //    //m_ai->SetIgnoreUpdateTime(8);
            //else if (SHADOWFLAME && !pTarget->HasAura(SHADOWFLAME) && LastSpellDestruction < 4)
            //    m_ai->CastSpell(SHADOWFLAME, *pTarget);
            //else if (SEARING_PAIN && LastSpellDestruction < 8)
            //    m_ai->CastSpell(SEARING_PAIN, *pTarget);
            //else if (SOUL_FIRE && LastSpellDestruction < 9)
            //    m_ai->CastSpell(SOUL_FIRE, *pTarget);
            //    //m_ai->SetIgnoreUpdateTime(6);
            //else if (SHADOWBURN && LastSpellDestruction < 11 && pTarget->GetHealth() < pTarget->GetMaxHealth() * 0.20 && !pTarget->HasAura(SHADOWBURN))
            //    m_ai->CastSpell(SHADOWBURN, *pTarget);
            //else if (HELLFIRE && LastSpellDestruction < 12 && !m_bot->HasAura(HELLFIRE) && m_ai->GetAttackerCount() >= 5 && m_ai->GetHealthPercent() >= 50)
            //    m_ai->CastSpell(HELLFIRE);
            //    m_ai->TellMaster("casting hellfire!");
            //    //m_ai->SetIgnoreUpdateTime(15);
            //else if (CURSE_OF_THE_ELEMENTS && !pTarget->HasAura(CURSE_OF_THE_ELEMENTS) && !pTarget->HasAura(SHADOWFLAME) && !pTarget->HasAura(CURSE_OF_AGONY) && !pTarget->HasAura(CURSE_OF_WEAKNESS) && LastSpellCurse < 2)
            //    m_ai->CastSpell(CURSE_OF_THE_ELEMENTS, *pTarget);
            //else if (CURSE_OF_WEAKNESS && !pTarget->HasAura(CURSE_OF_WEAKNESS) && !pTarget->HasAura(SHADOWFLAME) && !pTarget->HasAura(CURSE_OF_AGONY) && !pTarget->HasAura(CURSE_OF_THE_ELEMENTS) && LastSpellCurse < 3)
            //    m_ai->CastSpell(CURSE_OF_WEAKNESS, *pTarget);
            //else if (CURSE_OF_TONGUES && !pTarget->HasAura(CURSE_OF_TONGUES) && !pTarget->HasAura(SHADOWFLAME) && !pTarget->HasAura(CURSE_OF_WEAKNESS) && !pTarget->HasAura(CURSE_OF_AGONY) && !pTarget->HasAura(CURSE_OF_THE_ELEMENTS) && LastSpellCurse < 4)
            //    m_ai->CastSpell(CURSE_OF_TONGUES, *pTarget);
    }

    // No spec due to low level OR no spell found yet
    if (CORRUPTION && m_ai->In_Reach(pTarget,CORRUPTION) && !pTarget->HasAura(CORRUPTION) && CastSpell(CORRUPTION, pTarget))
        return RETURN_CONTINUE;
    if (FIRE && m_ai->In_Reach(pTarget,FIRE) && !pTarget->HasAura(FIRE) && CastSpell(FIRE, pTarget))
        return RETURN_CONTINUE;
    if (SHADOW_BOLT && m_ai->In_Reach(pTarget,SHADOW_BOLT))
        return CastSpell(SHADOW_BOLT, pTarget);

    return RETURN_NO_ACTION_OK;
} // end DoNextCombatManeuver
Example #8
0
CombatManeuverReturns PlayerbotHunterAI::DoNextCombatManeuverPVE(Unit *pTarget)
{
    if (!m_ai)    return RETURN_NO_ACTION_ERROR;
    if (!m_bot)   return RETURN_NO_ACTION_ERROR;
    if (!pTarget) return RETURN_NO_ACTION_ERROR;

    Unit* pVictim = pTarget->getVictim();

    // check for pet and heal if neccessary
    Pet *pet = m_bot->GetPet();
    // TODO: clarify/simplify: !pet->getDeathState() != ALIVE
    if (pet && PET_MEND > 0 && pet->isAlive() && pet->GetHealthPercent() < 50 && pVictim != m_bot && !pet->HasAura(PET_MEND, EFFECT_INDEX_0) && m_ai->CastSpell(PET_MEND, *m_bot))
    {
        m_ai->TellMaster("healing pet.");
        return RETURN_CONTINUE;
    }
    else if (pet && INTIMIDATION > 0 && pVictim == pet && !pet->HasAura(INTIMIDATION, EFFECT_INDEX_0) && m_ai->CastSpell(INTIMIDATION, *m_bot))
        return RETURN_CONTINUE;

    // racial traits
    if (m_bot->getRace() == RACE_ORC && !m_bot->HasAura(BLOOD_FURY, EFFECT_INDEX_0))
        m_ai->CastSpell(BLOOD_FURY, *m_bot);
    else if (m_bot->getRace() == RACE_TROLL && !m_bot->HasAura(BERSERKING, EFFECT_INDEX_0))
        m_ai->CastSpell(BERSERKING, *m_bot);

    // check if ranged combat is possible
    float dist = m_bot->GetCombatDistance(pTarget, true);
    if ((dist <= ATTACK_DISTANCE || !m_bot->GetUInt32Value(PLAYER_AMMO_ID)) && m_ai->GetCombatStyle() == PlayerbotAI::COMBAT_RANGED)
    {
        // switch to melee combat (target in melee range, out of ammo)
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_MELEE);
        if (!m_bot->GetUInt32Value(PLAYER_AMMO_ID))
            m_ai->TellMaster("Out of ammo!");
    }
    else if (dist > ATTACK_DISTANCE && m_ai->GetCombatStyle() == PlayerbotAI::COMBAT_MELEE)
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_RANGED);

    // Set appropriate aspect
    if (m_ai->GetCombatStyle() == PlayerbotAI::COMBAT_RANGED)
    {
        if (ASPECT_OF_THE_HAWK && !m_bot->HasAura(ASPECT_OF_THE_HAWK, EFFECT_INDEX_0))
            m_ai->CastSpell(ASPECT_OF_THE_HAWK, *m_bot);
    }
    else
    {
        if (ASPECT_OF_THE_MONKEY && !m_bot->HasAura(ASPECT_OF_THE_MONKEY, EFFECT_INDEX_0))
            m_ai->CastSpell(ASPECT_OF_THE_MONKEY, *m_bot);
    }

    // activate auto shot: Reworked to account for AUTO_SHOT being a triggered spell
    if (AUTO_SHOT > 0 && m_ai->GetCombatStyle() == PlayerbotAI::COMBAT_RANGED && m_ai->GetCurrentSpellId() != AUTO_SHOT)
        m_bot->CastSpell(pTarget, AUTO_SHOT, true);

    // damage spells
    if (m_ai->GetCombatStyle() == PlayerbotAI::COMBAT_RANGED)
    {
        if (HUNTERS_MARK > 0 && !pTarget->HasAura(HUNTERS_MARK, EFFECT_INDEX_0) && m_ai->CastSpell(HUNTERS_MARK, *pTarget))
            return RETURN_CONTINUE;
        else if (RAPID_FIRE > 0 && !m_bot->HasAura(RAPID_FIRE, EFFECT_INDEX_0) && m_ai->CastSpell(RAPID_FIRE, *m_bot))
            return RETURN_CONTINUE;
        else if (MULTI_SHOT > 0 && m_ai->GetAttackerCount() >= 3 && m_ai->CastSpell(MULTI_SHOT, *pTarget))
            return RETURN_CONTINUE;
        else if (ARCANE_SHOT > 0 && m_ai->CastSpell(ARCANE_SHOT, *pTarget))
            return RETURN_CONTINUE;
        else if (CONCUSSIVE_SHOT > 0 && !pTarget->HasAura(CONCUSSIVE_SHOT, EFFECT_INDEX_0) && m_ai->CastSpell(CONCUSSIVE_SHOT, *pTarget))
            return RETURN_CONTINUE;
        else if (EXPLOSIVE_SHOT > 0 && !pTarget->HasAura(EXPLOSIVE_SHOT, EFFECT_INDEX_0) && m_ai->CastSpell(EXPLOSIVE_SHOT, *pTarget))
            return RETURN_CONTINUE;
        else if (VIPER_STING > 0 && pTarget->GetPower(POWER_MANA) > 0 && m_ai->GetManaPercent() < 70 && !pTarget->HasAura(VIPER_STING, EFFECT_INDEX_0) && m_ai->CastSpell(VIPER_STING, *pTarget))
            return RETURN_CONTINUE;
        else if (SERPENT_STING > 0 && !pTarget->HasAura(SERPENT_STING, EFFECT_INDEX_0) && !pTarget->HasAura(SCORPID_STING, EFFECT_INDEX_0) &&  !pTarget->HasAura(VIPER_STING, EFFECT_INDEX_0) && m_ai->CastSpell(SERPENT_STING, *pTarget))
            return RETURN_CONTINUE;
        else if (SCORPID_STING > 0 && !pTarget->HasAura(WYVERN_STING, EFFECT_INDEX_0) && !pTarget->HasAura(SCORPID_STING, EFFECT_INDEX_0) && !pTarget->HasAura(SERPENT_STING, EFFECT_INDEX_0) && !pTarget->HasAura(VIPER_STING, EFFECT_INDEX_0) && m_ai->CastSpell(SCORPID_STING, *pTarget))
            return RETURN_CONTINUE;
        else if (CHIMERA_SHOT > 0 && m_ai->CastSpell(CHIMERA_SHOT, *pTarget))
            return RETURN_CONTINUE;
        else if (VOLLEY > 0 && m_ai->GetAttackerCount() >= 3 && m_ai->CastSpell(VOLLEY, *pTarget))
            return RETURN_CONTINUE;
        else if (BLACK_ARROW > 0 && !pTarget->HasAura(BLACK_ARROW, EFFECT_INDEX_0) && m_ai->CastSpell(BLACK_ARROW, *pTarget))
            return RETURN_CONTINUE;
        else if (AIMED_SHOT > 0 && m_ai->CastSpell(AIMED_SHOT, *pTarget))
            return RETURN_CONTINUE;
        else if (STEADY_SHOT > 0 && m_ai->CastSpell(STEADY_SHOT, *pTarget))
            return RETURN_CONTINUE;
        else if (KILL_SHOT > 0 && pTarget->GetHealthPercent() < 20 && m_ai->CastSpell(KILL_SHOT, *pTarget))
            return RETURN_CONTINUE;
        else
            return RETURN_NO_ACTION_OK;
    }
    else
    {
        if (RAPTOR_STRIKE > 0 && m_ai->CastSpell(RAPTOR_STRIKE, *pTarget))
            return RETURN_CONTINUE;
        else if (EXPLOSIVE_TRAP > 0 && !pTarget->HasAura(EXPLOSIVE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(ARCANE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(IMMOLATION_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(FROST_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(BEAR_TRAP, EFFECT_INDEX_0) && m_ai->CastSpell(EXPLOSIVE_TRAP, *pTarget))
            return RETURN_CONTINUE;
        else if (WING_CLIP > 0 && !pTarget->HasAura(WING_CLIP, EFFECT_INDEX_0) && m_ai->CastSpell(WING_CLIP, *pTarget))
            return RETURN_CONTINUE;
        else if (IMMOLATION_TRAP > 0 && !pTarget->HasAura(IMMOLATION_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(ARCANE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(EXPLOSIVE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(FROST_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(BEAR_TRAP, EFFECT_INDEX_0) && m_ai->CastSpell(IMMOLATION_TRAP, *pTarget))
            return RETURN_CONTINUE;
        else if (MONGOOSE_BITE > 0 && m_ai->CastSpell(MONGOOSE_BITE, *pTarget))
            return RETURN_CONTINUE;
        else if (FROST_TRAP > 0 && !pTarget->HasAura(FROST_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(ARCANE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(IMMOLATION_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(EXPLOSIVE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(BEAR_TRAP, EFFECT_INDEX_0) && m_ai->CastSpell(FROST_TRAP, *pTarget))
            return RETURN_CONTINUE;
        else if (ARCANE_TRAP > 0 && !pTarget->HasAura(ARCANE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(BEAR_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(EXPLOSIVE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(IMMOLATION_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(FROST_TRAP, EFFECT_INDEX_0) && m_ai->CastSpell(ARCANE_TRAP, *pTarget))
            return RETURN_CONTINUE;
        else if (DETERRENCE > 0 && pVictim == m_bot && m_bot->GetHealthPercent() < 50 && !m_bot->HasAura(DETERRENCE, EFFECT_INDEX_0) && m_ai->CastSpell(DETERRENCE, *m_bot))
            return RETURN_CONTINUE;
        else if (m_bot->getRace() == RACE_TAUREN && !pTarget->HasAura(WAR_STOMP, EFFECT_INDEX_0) && m_ai->CastSpell(WAR_STOMP, *pTarget))
            return RETURN_CONTINUE;
        else if (m_bot->getRace() == RACE_BLOODELF && !pTarget->HasAura(ARCANE_TORRENT, EFFECT_INDEX_0) && m_ai->CastSpell(ARCANE_TORRENT, *pTarget))
            return RETURN_CONTINUE;
        else if (m_bot->getRace() == RACE_DWARF && m_bot->HasAuraState(AURA_STATE_DEADLY_POISON) && m_ai->CastSpell(STONEFORM, *m_bot))
            return RETURN_CONTINUE;
        else if (m_bot->getRace() == RACE_NIGHTELF && pVictim == m_bot && m_ai->GetHealthPercent() < 25 && !m_bot->HasAura(SHADOWMELD, EFFECT_INDEX_0) && m_ai->CastSpell(SHADOWMELD, *m_bot))
            return RETURN_CONTINUE;
        else if (m_bot->getRace() == RACE_DRAENEI && m_ai->GetHealthPercent() < 25 && !m_bot->HasAura(GIFT_OF_THE_NAARU, EFFECT_INDEX_0) && m_ai->CastSpell(GIFT_OF_THE_NAARU, *m_bot))
            return RETURN_CONTINUE;
        else if (pet && pet->isAlive() && MISDIRECTION > 0 && pVictim == m_bot && !m_bot->HasAura(MISDIRECTION, EFFECT_INDEX_0) && m_ai->CastSpell(MISDIRECTION, *pet))
            return RETURN_CONTINUE;
        /*else if(FREEZING_TRAP > 0 && !pTarget->HasAura(FREEZING_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(ARCANE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(EXPLOSIVE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(BEAR_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(IMMOLATION_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(FROST_TRAP, EFFECT_INDEX_0) && m_ai->CastSpell(FREEZING_TRAP,*pTarget) )
            out << " > Freezing Trap"; // this can trap your bots too
           else if(BEAR_TRAP > 0 && !pTarget->HasAura(BEAR_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(ARCANE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(EXPLOSIVE_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(IMMOLATION_TRAP, EFFECT_INDEX_0) && !pTarget->HasAura(FROST_TRAP, EFFECT_INDEX_0) && m_ai->CastSpell(BEAR_TRAP,*pTarget) )
            out << " > Bear Trap"; // this was just too annoying :)
           else if(DISENGAGE > 0 && pVictim && m_ai->CastSpell(DISENGAGE,*pTarget) )
            out << " > Disengage!"; // attempt to return to ranged combat*/
        else RETURN_NO_ACTION_OK;
    }

    return RETURN_NO_ACTION_OK;
} // end DoNextCombatManeuver