void PlayerbotWarlockAI::CheckDemon()
{
    uint32 spec = m_bot->GetSpec();
    uint8 shardCount = m_bot->GetItemCount(SOUL_SHARD, false, nullptr);
    Pet *pet = m_bot->GetPet();

    //Assign demon of choice
    if (spec == WARLOCK_SPEC_AFFLICTION)
        m_demonOfChoice = DEMON_FELHUNTER;
    else if (spec == WARLOCK_SPEC_DEMONOLOGY)
        m_demonOfChoice = (DEMON_FELGUARD > 0 ? DEMON_FELGUARD : DEMON_SUCCUBUS);
    else if (spec == WARLOCK_SPEC_DESTRUCTION)
        m_demonOfChoice = DEMON_IMP;

    // Summon demon
    if (!pet || m_isTempImp || pet->GetEntry() != m_demonOfChoice)
    {
        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 (m_ai->CastSpell(summonSpellId))
            {
                //m_ai->TellMaster("Summoning favorite demon...");
                m_isTempImp = false;
                return;
            }
        }
        else if (!pet && SUMMON_IMP && m_ai->CastSpell(SUMMON_IMP))
        {
            if (m_demonOfChoice != DEMON_IMP)
                m_isTempImp = true;

            //m_ai->TellMaster("Summoning Imp...");
            return;
        }
    }
}
示例#2
0
void WorldSession::SendStablePetCallback(PreparedQueryResult result, uint64 guid)
{
    if (!GetPlayer())
        return;

    TC_LOG_DEBUG("network", "WORLD: Recv MSG_LIST_STABLED_PETS Send.");

    WorldPacket data(MSG_LIST_STABLED_PETS, 200);           // guess size

    data << uint64 (guid);

    Pet* pet = _player->GetPet();

    size_t wpos = data.wpos();
    data << uint8(0);                                       // place holder for slot show number

    data << uint8(GetPlayer()->m_stableSlots);

    uint8 num = 0;                                          // counter for place holder

    // not let move dead pet in slot
    if (pet && pet->IsAlive() && pet->getPetType() == HUNTER_PET)
    {
        data << uint32(num);                                // 4.x unknown, some kind of order?
        data << uint32(pet->GetCharmInfo()->GetPetNumber());
        data << uint32(pet->GetEntry());
        data << uint32(pet->getLevel());
        data << pet->GetName();                             // petname
        data << uint8(1);                                   // 1 = current, 2/3 = in stable (any from 4, 5, ... create problems with proper show)
        ++num;
    }

    if (result)
    {
        do
        {
            Field* fields = result->Fetch();


            data << uint32(num);	    
            data << uint32(fields[1].GetUInt32());          // petnumber
            data << uint32(fields[2].GetUInt32());          // creature entry
            data << uint32(fields[3].GetUInt16());          // level
            data << fields[4].GetString();                  // name
            data << uint8(2);                               // 1 = current, 2/3 = in stable (any from 4, 5, ... create problems with proper show)

            ++num;
        }
        while (result->NextRow());
    }

    data.put<uint8>(wpos, num);                             // set real data to placeholder
    SendPacket(&data);

    SendStableResult(STABLE_ERR_NONE);
}
示例#3
0
void WorldSession::SendStablePetCallback(QueryResult result, uint64 guid)
{
    if (!GetPlayer())
        return;

    sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv MSG_LIST_STABLED_PETS Send.");

    WorldPacket data(MSG_LIST_STABLED_PETS, 200);           // guess size

    data << uint64 (guid);

    Pet* pet = _player->GetPet();

    size_t wpos = data.wpos();
    data << uint8(0);                                       // place holder for slot show number

    data << uint8(GetPlayer()->_petSlotUsed);

    uint8 num = 0;                                          // counter for place holder

    // not let move dead pet in slot
    if (pet && pet->isAlive() && pet->getPetType() == HUNTER_PET)
    {
        data << uint32(_player->_currentPetSlot);
        data << uint32(pet->GetCharmInfo()->GetPetNumber());
        data << uint32(pet->GetEntry());
        data << uint32(pet->getLevel());
        data << pet->GetName();                             // petname
        data << uint8(1);                                   // 1 = current, 2/3 = in stable (any from 4, 5, ... create problems with proper show)
        ++num;
    }

    if (result)
    {
        do
        {
            Field *fields = result->Fetch();

            data << uint32(fields[1].GetUInt32());          // slot
            data << uint32(fields[2].GetUInt32());          // petnumber
            data << uint32(fields[3].GetUInt32());          // creature entry
            data << uint32(fields[4].GetUInt16());          // level
            data << fields[5].GetString();                  // name
            data << uint8(fields[1].GetUInt32() <= PET_SLOT_STABLE_FIRST ? 1 : 2);       // 1 = current, 2/3 = in stable (any from 4, 5, ... create problems with proper show)

            ++num;
        }
        while (result->NextRow());
    }

    data.put<uint8>(wpos, num);                             // set real data to placeholder
    SendPacket(&data);
}
示例#4
0
void WorldSession::SendStablePet(uint64 guid )
{
    sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS Send.");

    WorldPacket data(MSG_LIST_STABLED_PETS, 200);           // guess size
    data << uint64 ( guid );

    Pet *pet = _player->GetPet();

    size_t wpos = data.wpos();
    data << uint8(0);                                       // place holder for slot show number

    data << uint8(GetPlayer()->m_stableSlots);

    uint8 num = 0;                                          // counter for place holder

    // not let move dead pet in slot
    if(pet && pet->isAlive() && pet->getPetType()==HUNTER_PET)
    {
        data << uint32(pet->GetCharmInfo()->GetPetNumber());
        data << uint32(pet->GetEntry());
        data << uint32(pet->getLevel());
        data << pet->GetName();                             // petname
        data << uint8(1);                                   // 1 = current, 2/3 = in stable (any from 4,5,... create problems with proper show)
        ++num;
    }

    //                                                     0      1   2      3      4
    QueryResult* result = CharacterDatabase.PQuery("SELECT owner, id, entry, level, name FROM character_pet WHERE owner = '%u' AND slot >= '%u' AND slot <= '%u' ORDER BY slot",
        _player->GetGUIDLow(),PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT);

    if(result)
    {
        do
        {
            Field *fields = result->Fetch();

            data << uint32(fields[1].GetUInt32());          // petnumber
            data << uint32(fields[2].GetUInt32());          // creature entry
            data << uint32(fields[3].GetUInt32());          // level
            data << fields[4].GetString();                  // name
            data << uint8(2);                               // 1 = current, 2/3 = in stable (any from 4,5,... create problems with proper show)

            ++num;
        }while( result->NextRow() );

        delete result;
    }

    data.put<uint8>(wpos, num);                             // set real data to placeholder
    SendPacket(&data);
}
示例#5
0
void WorldSession::SendStablePetCallback(ObjectGuid guid, PreparedQueryResult result)
{
    if (!GetPlayer())
        return;

    WorldPackets::Pet::PetStableList packet;

    packet.StableMaster = guid;

    Pet* pet = _player->GetPet();

    int32 petSlot = 0;
    // not let move dead pet in slot
    if (pet && pet->IsAlive() && pet->getPetType() == HUNTER_PET)
    {
        WorldPackets::Pet::PetStableInfo stableEntry;
        stableEntry.PetSlot = petSlot;
        stableEntry.PetNumber = pet->GetCharmInfo()->GetPetNumber();
        stableEntry.CreatureID = pet->GetEntry();
        stableEntry.DisplayID = pet->GetDisplayId();
        stableEntry.ExperienceLevel = pet->getLevel();
        stableEntry.PetFlags = PET_STABLE_ACTIVE;
        stableEntry.PetName = pet->GetName();
        ++petSlot;

        packet.Pets.push_back(stableEntry);
    }

    if (result)
    {
        do
        {
            Field* fields = result->Fetch();
            WorldPackets::Pet::PetStableInfo stableEntry;

            stableEntry.PetSlot = petSlot;
            stableEntry.PetNumber = fields[1].GetUInt32();          // petnumber
            stableEntry.CreatureID = fields[2].GetUInt32();         // creature entry
            stableEntry.DisplayID = fields[5].GetUInt32();          // creature displayid
            stableEntry.ExperienceLevel = fields[3].GetUInt16();    // level
            stableEntry.PetFlags = PET_STABLE_INACTIVE;
            stableEntry.PetName = fields[4].GetString();            // Name

            ++petSlot;
            packet.Pets.push_back(stableEntry);
        }
        while (result->NextRow());
    }

    SendPacket(packet.Write());
}
示例#6
0
void WorldSession::SendStablePet(uint64 guid)
{
    sLog->outDebug("WORLD: Recv MSG_LIST_STABLED_PETS Send.");

    WorldPacket data(MSG_LIST_STABLED_PETS, 200);           // guess size
    data << uint64 (guid);

    Pet *pet = _player->GetPet();

    data << uint8(0);                                       // place holder for slot show number
    data << uint8(GetPlayer()->m_stableSlots);

    uint8 num = 0;                                          // counter for place holder

    // not let move dead pet in slot
    if (pet && pet->isAlive() && pet->getPetType() == HUNTER_PET)
    {
        data << uint32(pet->GetCharmInfo()->GetPetNumber());
        data << uint32(pet->GetEntry());
        data << uint32(pet->getLevel());
        data << pet->GetName();                             // petname
        data << uint32(pet->GetLoyaltyLevel());             // loyalty
        data << uint8(0x01);                                // client slot 1 == current pet (0)
        ++num;
    }

    //                                                            0      1     2   3      4      5        6
    QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT owner, slot, id, entry, level, loyalty, name FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 3", _player->GetGUIDLow());

    if (result)
    {
        do
        {
            Field *fields = result->Fetch();

            data << uint32(fields[2].GetUInt32());          // petnumber
            data << uint32(fields[3].GetUInt32());          // creature entry
            data << uint32(fields[4].GetUInt32());          // level
            data << fields[6].GetString();                  // name
            data << uint32(fields[5].GetUInt32());          // loyalty
            data << uint8(fields[1].GetUInt32()+1);         // slot

            ++num;
        }while (result->NextRow());
    }

    data.put<uint8>(8, num);                                // set real data to placeholder
    SendPacket(&data);
}
示例#7
0
void PlayerbotWarlockAI::DoNextCombatManeuver(Unit *pTarget)
{
    PlayerbotAI* ai = GetAI();
    if (!ai)
        return;

    switch (ai->GetScenarioType())
    {
        case PlayerbotAI::SCENARIO_DUEL:
        {
            if (SHADOW_BOLT > 0)
                ai->CastSpell(SHADOW_BOLT);
            return;
        }
        default:
            break;
    }

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

    //ai->SetMovementOrder( PlayerbotAI::MOVEMENT_FOLLOW, GetMaster() ); // dont want to melee mob

    ai->SetInFront(pTarget);
    Player *m_bot = GetPlayerBot();
    Unit* pVictim = pTarget->getVictim();
    Pet *pet = m_bot->GetPet();

    // Empower demon
    if (pet && DEMONIC_EMPOWERMENT && !m_bot->HasSpellCooldown(DEMONIC_EMPOWERMENT))
        ai->CastSpell(DEMONIC_EMPOWERMENT);

    // Use voidwalker sacrifice on low health if possible
    if (ai->GetHealthPercent() < 50)
        if (pet && pet->GetEntry() == DEMON_VOIDWALKER && SACRIFICE && !m_bot->HasAura(SACRIFICE))
            ai->CastPetSpell(SACRIFICE);

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

    // Damage Spells
    switch (SpellSequence)
    {
        case SPELL_CURSES:
            if (CURSE_OF_AGONY && !pTarget->HasAura(CURSE_OF_AGONY) && !pTarget->HasAura(SHADOWFLAME) && LastSpellCurse < 1)
            {
                ai->CastSpell(CURSE_OF_AGONY, *pTarget);
                SpellSequence = SPELL_AFFLICTION;
                ++LastSpellCurse;
                break;
            }
            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)
            {
                ai->CastSpell(CURSE_OF_THE_ELEMENTS, *pTarget);
                SpellSequence = SPELL_AFFLICTION;
                ++LastSpellCurse;
                break;
            }
            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)
            {
                ai->CastSpell(CURSE_OF_WEAKNESS, *pTarget);
                SpellSequence = SPELL_AFFLICTION;
                ++LastSpellCurse;
                break;
            }
            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)
            {
                ai->CastSpell(CURSE_OF_TONGUES, *pTarget);
                SpellSequence = SPELL_AFFLICTION;
                ++LastSpellCurse;
                break;
            }
            LastSpellCurse = 0;
        //SpellSequence = SPELL_AFFLICTION;
        //break;

        case SPELL_AFFLICTION:
            if (LIFE_TAP && LastSpellAffliction < 1 && ai->GetManaPercent() <= 50 && ai->GetHealthPercent() > 50)
            {
                ai->CastSpell(LIFE_TAP, *m_bot);
                SpellSequence = SPELL_DESTRUCTION;
                ++LastSpellAffliction;
                break;
            }
            else if (CORRUPTION && !pTarget->HasAura(CORRUPTION) && !pTarget->HasAura(SHADOWFLAME) && !pTarget->HasAura(SEED_OF_CORRUPTION) && LastSpellAffliction < 2)
            {
                ai->CastSpell(CORRUPTION, *pTarget);
                SpellSequence = SPELL_DESTRUCTION;
                ++LastSpellAffliction;
                break;
            }
            else if (DRAIN_SOUL && pTarget->GetHealth() < pTarget->GetMaxHealth() * 0.40 && !pTarget->HasAura(DRAIN_SOUL) && LastSpellAffliction < 3)
            {
                ai->CastSpell(DRAIN_SOUL, *pTarget);
                //ai->SetIgnoreUpdateTime(15);
                SpellSequence = SPELL_DESTRUCTION;
                ++LastSpellAffliction;
                break;
            }
            else if (DRAIN_LIFE && LastSpellAffliction < 4 && !pTarget->HasAura(DRAIN_SOUL) && !pTarget->HasAura(SEED_OF_CORRUPTION) && !pTarget->HasAura(DRAIN_LIFE) && !pTarget->HasAura(DRAIN_MANA) && ai->GetHealthPercent() <= 70)
            {
                ai->CastSpell(DRAIN_LIFE, *pTarget);
                //ai->SetIgnoreUpdateTime(5);
                SpellSequence = SPELL_DESTRUCTION;
                ++LastSpellAffliction;
                break;
            }
            else if (UNSTABLE_AFFLICTION && LastSpellAffliction < 5 && !pTarget->HasAura(UNSTABLE_AFFLICTION) && !pTarget->HasAura(SHADOWFLAME))
            {
                ai->CastSpell(UNSTABLE_AFFLICTION, *pTarget);
                SpellSequence = SPELL_DESTRUCTION;
                ++LastSpellAffliction;
                break;
            }
            else if (HAUNT && LastSpellAffliction < 6 && !pTarget->HasAura(HAUNT))
            {
                ai->CastSpell(HAUNT, *pTarget);
                SpellSequence = SPELL_DESTRUCTION;
                ++LastSpellAffliction;
                break;
            }
            else if (SEED_OF_CORRUPTION && !pTarget->HasAura(SEED_OF_CORRUPTION) && LastSpellAffliction < 7)
            {
                ai->CastSpell(SEED_OF_CORRUPTION, *pTarget);
                SpellSequence = SPELL_DESTRUCTION;
                ++LastSpellAffliction;
                break;
            }
            else if (HOWL_OF_TERROR && !pTarget->HasAura(HOWL_OF_TERROR) && ai->GetAttackerCount() > 3 && LastSpellAffliction < 8)
            {
                ai->CastSpell(HOWL_OF_TERROR, *pTarget);
                ai->TellMaster("casting howl of terror!");
                SpellSequence = SPELL_DESTRUCTION;
                ++LastSpellAffliction;
                break;
            }
            else if (FEAR && !pTarget->HasAura(FEAR) && pVictim == m_bot && ai->GetAttackerCount() >= 2 && LastSpellAffliction < 9)
            {
                ai->CastSpell(FEAR, *pTarget);
                //ai->TellMaster("casting fear!");
                //ai->SetIgnoreUpdateTime(1.5);
                SpellSequence = SPELL_DESTRUCTION;
                ++LastSpellAffliction;
                break;
            }
            else if ((pet)
                     && (DARK_PACT > 0 && ai->GetManaPercent() <= 50 && LastSpellAffliction < 10 && pet->GetPower(POWER_MANA) > 0))
            {
                ai->CastSpell(DARK_PACT, *m_bot);
                SpellSequence = SPELL_DESTRUCTION;
                ++LastSpellAffliction;
                break;
            }
            LastSpellAffliction = 0;
        //SpellSequence = SPELL_DESTRUCTION;
        //break;

        case SPELL_DESTRUCTION:
            if (SHADOWFURY && LastSpellDestruction < 1 && !pTarget->HasAura(SHADOWFURY))
            {
                ai->CastSpell(SHADOWFURY, *pTarget);
                SpellSequence = SPELL_CURSES;
                ++LastSpellDestruction;
                break;
            }
            else if (SHADOW_BOLT && LastSpellDestruction < 2)
            {
                ai->CastSpell(SHADOW_BOLT, *pTarget);
                SpellSequence = SPELL_CURSES;
                ++LastSpellDestruction;
                break;
            }
            else if (RAIN_OF_FIRE && LastSpellDestruction < 3 && ai->GetAttackerCount() >= 3)
            {
                ai->CastSpell(RAIN_OF_FIRE, *pTarget);
                //ai->TellMaster("casting rain of fire!");
                //ai->SetIgnoreUpdateTime(8);
                SpellSequence = SPELL_CURSES;
                ++LastSpellDestruction;
                break;
            }
            else if (SHADOWFLAME && !pTarget->HasAura(SHADOWFLAME) && LastSpellDestruction < 4)
            {
                ai->CastSpell(SHADOWFLAME, *pTarget);
                SpellSequence = SPELL_CURSES;
                ++LastSpellDestruction;
                break;
            }
            else if (IMMOLATE && !pTarget->HasAura(IMMOLATE) && !pTarget->HasAura(SHADOWFLAME) && LastSpellDestruction < 5)
            {
                ai->CastSpell(IMMOLATE, *pTarget);
                SpellSequence = SPELL_CURSES;
                ++LastSpellDestruction;
                break;
            }
            else if (CONFLAGRATE && LastSpellDestruction < 6)
            {
                ai->CastSpell(CONFLAGRATE, *pTarget);
                SpellSequence = SPELL_CURSES;
                ++LastSpellDestruction;
                break;
            }
            else if (INCINERATE && LastSpellDestruction < 7)
            {
                ai->CastSpell(INCINERATE, *pTarget);
                SpellSequence = SPELL_CURSES;
                ++LastSpellDestruction;
                break;
            }
            else if (SEARING_PAIN && LastSpellDestruction < 8)
            {
                ai->CastSpell(SEARING_PAIN, *pTarget);
                SpellSequence = SPELL_CURSES;
                ++LastSpellDestruction;
                break;
            }
            else if (SOUL_FIRE && LastSpellDestruction < 9)
            {
                ai->CastSpell(SOUL_FIRE, *pTarget);
                //ai->SetIgnoreUpdateTime(6);
                SpellSequence = SPELL_CURSES;
                ++LastSpellDestruction;
                break;
            }
            else if (CHAOS_BOLT && LastSpellDestruction < 10)
            {
                ai->CastSpell(CHAOS_BOLT, *pTarget);
                SpellSequence = SPELL_CURSES;
                ++LastSpellDestruction;
                break;
            }
            else if (SHADOWBURN && LastSpellDestruction < 11 && pTarget->GetHealth() < pTarget->GetMaxHealth() * 0.20 && !pTarget->HasAura(SHADOWBURN))
            {
                ai->CastSpell(SHADOWBURN, *pTarget);
                SpellSequence = SPELL_CURSES;
                ++LastSpellDestruction;
                break;
            }
            else if (HELLFIRE && LastSpellDestruction < 12 && !m_bot->HasAura(HELLFIRE) && ai->GetAttackerCount() >= 5 && ai->GetHealthPercent() >= 50)
            {
                ai->CastSpell(HELLFIRE);
                ai->TellMaster("casting hellfire!");
                //ai->SetIgnoreUpdateTime(15);
                SpellSequence = SPELL_CURSES;
                ++LastSpellDestruction;
                break;
            }
            else
            {
                LastSpellDestruction = 0;
                SpellSequence = SPELL_CURSES;
            }
    }
} // end DoNextCombatManeuver
示例#8
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
void PlayerbotWarlockAI::CheckDemon()
{
    uint32 spec = m_bot->GetSpec();
    uint8 shardCount = m_bot->GetItemCount(SOUL_SHARD, false, nullptr);
    Pet *pet = m_bot->GetPet();
    uint32 demonOfChoice;

    // If pet other than imp is active: return
    if (pet && pet->GetEntry() != DEMON_IMP)
        return;

    // Assign demon of choice based on spec
    if (spec == WARLOCK_SPEC_AFFLICTION)
        demonOfChoice = DEMON_FELHUNTER;
    else if (spec == WARLOCK_SPEC_DEMONOLOGY)
        demonOfChoice = DEMON_SUCCUBUS;
    else    // Destruction spec or no spec found
        demonOfChoice = DEMON_IMP;

    // Summon demon
    if (!pet || m_isTempImp)
    {
        uint32 summonSpellId;
        if (demonOfChoice != DEMON_IMP && shardCount > 0)
        {
            switch (demonOfChoice)
            {
                case DEMON_VOIDWALKER:
                    summonSpellId = SUMMON_VOIDWALKER;
                    break;

                case DEMON_FELHUNTER:
                    summonSpellId = SUMMON_FELHUNTER;
                    break;

                case DEMON_SUCCUBUS:
                    summonSpellId = SUMMON_SUCCUBUS;
                    break;

                default:
                    summonSpellId = 0;
            }

            if (summonSpellId && m_ai->CastSpell(summonSpellId))
            {
                //m_ai->TellMaster("Summoning favorite demon...");
                m_isTempImp = false;
                return;
            }
        }

        if (!pet && SUMMON_IMP && m_ai->CastSpell(SUMMON_IMP))
        {
            if (demonOfChoice != DEMON_IMP)
                m_isTempImp = true;
            else
                m_isTempImp = false;

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

    return;
}
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
示例#12
0
uint8 WorldSession::HandleLoadPetFromDBFirstCallback(PreparedQueryResult result, uint8 asynchLoadType)
{
    if (!GetPlayer() || GetPlayer()->GetPet() || GetPlayer()->GetVehicle() || GetPlayer()->IsSpectator())
        return PET_LOAD_ERROR;

    if (!result)
        return PET_LOAD_NO_RESULT;

    Field* fields = result->Fetch();

	// Xinef: this can happen if fetch is called twice, impossibru.
	if (!fields)
		return PET_LOAD_ERROR;

	Player* owner = GetPlayer();

    // update for case of current pet "slot = 0"
    uint32 petentry = fields[1].GetUInt32();
    if (!petentry)
        return PET_LOAD_NO_RESULT;

	uint8 petSlot = fields[7].GetUInt8();
	bool current = petSlot == PET_SAVE_AS_CURRENT;
    uint32 summon_spell_id = fields[15].GetUInt32();
    SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(summon_spell_id); // CANT BE NULL
    bool is_temporary_summoned = spellInfo && spellInfo->GetDuration() > 0;
    uint32 pet_number = fields[0].GetUInt32();
	uint32 savedhealth = fields[10].GetUInt32();
    uint32 savedmana = fields[11].GetUInt32();
	PetType pet_type = PetType(fields[16].GetUInt8());

	// xinef: BG resurrect, overwrite saved value
	if (asynchLoadType == PET_LOAD_BG_RESURRECT)
		savedhealth = 1;

	if (pet_type == HUNTER_PET && savedhealth == 0 && asynchLoadType != PET_LOAD_SUMMON_DEAD_PET)
	{
		WorldPacket data(SMSG_CAST_FAILED, 1+4+1+4);
        data << uint8(0);
        data << uint32(883);
        data << uint8(SPELL_FAILED_TARGETS_DEAD);
        SendPacket(&data);
		owner->RemoveSpellCooldown(883, false);
		return PET_LOAD_ERROR;
	}

    // check temporary summoned pets like mage water elemental
    if (current && is_temporary_summoned)
        return PET_LOAD_ERROR;

    if (pet_type == HUNTER_PET)
    {
        CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petentry);
        if (!creatureInfo || !creatureInfo->IsTameable(owner->CanTameExoticPets()))
            return PET_LOAD_ERROR;
    }

    Map* map = owner->GetMap();
    uint32 guid = sObjectMgr->GenerateLowGuid(HIGHGUID_PET);
	Pet* pet = new Pet(owner, pet_type);
	LoadPetFromDBQueryHolder* holder = new LoadPetFromDBQueryHolder(pet_number, current, uint32(time(NULL) - fields[14].GetUInt32()), fields[13].GetString(), savedhealth, savedmana);
    if (!pet->Create(guid, map, owner->GetPhaseMask(), petentry, pet_number) || !holder->Initialize())
	{
		delete pet;
		delete holder;
        return PET_LOAD_ERROR;
	}

    float px, py, pz;
    owner->GetClosePoint(px, py, pz, pet->GetObjectSize(), PET_FOLLOW_DIST, pet->GetFollowAngle());
    if (!pet->IsPositionValid())
    {
        sLog->outError("Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)", pet->GetGUIDLow(), pet->GetEntry(), pet->GetPositionX(), pet->GetPositionY());
		delete pet;
		delete holder;
        return PET_LOAD_ERROR;
    }

	pet->SetLoading(true);
    pet->Relocate(px, py, pz, owner->GetOrientation());
    pet->setPetType(pet_type);
    pet->setFaction(owner->getFaction());
    pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id);

    if (pet->IsCritter())
    {
        map->AddToMap(pet->ToCreature(), true);
		pet->SetLoading(false); // xinef, mine
		delete holder;
        return PET_LOAD_OK;
    }

    pet->GetCharmInfo()->SetPetNumber(pet_number, pet->IsPermanentPetFor(owner));

    pet->SetDisplayId(fields[3].GetUInt32());
    pet->SetNativeDisplayId(fields[3].GetUInt32());
    uint32 petlevel = fields[4].GetUInt8();
    pet->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
    pet->SetName(fields[8].GetString());

    switch (pet->getPetType())
    {
        case SUMMON_PET:
            petlevel = owner->getLevel();

			if (pet->IsPetGhoul())
				pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 0x400); // class = rogue
			else
				pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 0x800); // class = mage

            pet->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
                                                            // this enables popup window (pet dismiss, cancel)
            break;
        case HUNTER_PET:
            pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); // class = warrior, gender = none, power = focus
            pet->SetSheath(SHEATH_STATE_MELEE);
            pet->SetByteFlag(UNIT_FIELD_BYTES_2, 2, fields[9].GetBool() ? UNIT_CAN_BE_ABANDONED : UNIT_CAN_BE_RENAMED | UNIT_CAN_BE_ABANDONED);

            pet->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
                                                            // this enables popup window (pet abandon, cancel)
            pet->SetMaxPower(POWER_HAPPINESS, pet->GetCreatePowers(POWER_HAPPINESS));
            pet->SetPower(POWER_HAPPINESS, fields[12].GetUInt32());
            pet->setPowerType(POWER_FOCUS);
            break;
        default:
            if (!pet->IsPetGhoul())
                sLog->outError("Pet have incorrect type (%u) for pet loading.", pet->getPetType());
            break;
    }

    pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); // cast can't be helped here
    pet->SetCreatorGUID(owner->GetGUID());
	owner->SetMinion(pet, true);

    pet->InitStatsForLevel(petlevel);
    pet->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32());

    pet->SynchronizeLevelWithOwner();

    pet->SetReactState(ReactStates(fields[6].GetUInt8()));
    pet->SetCanModifyStats(true);

    // set current pet as current
    // 0=current
    // 1..MAX_PET_STABLES in stable slot
    // PET_SAVE_NOT_IN_SLOT(100) = not stable slot (summoning))
    if (petSlot)
    {
        SQLTransaction trans = CharacterDatabase.BeginTransaction();

        PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UDP_CHAR_PET_SLOT_BY_SLOT_EXCLUDE_ID);
        stmt->setUInt8(0, uint8(PET_SAVE_NOT_IN_SLOT));
        stmt->setUInt32(1, owner->GetGUIDLow());
        stmt->setUInt8(2, uint8(PET_SAVE_AS_CURRENT));
        stmt->setUInt32(3, pet_number);
        trans->Append(stmt);

        stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID);
        stmt->setUInt8(0, uint8(PET_SAVE_AS_CURRENT));
        stmt->setUInt32(1, owner->GetGUIDLow());
        stmt->setUInt32(2, pet_number);
        trans->Append(stmt);

        CharacterDatabase.CommitTransaction(trans);
    }

    // Send fake summon spell cast - this is needed for correct cooldown application for spells
    // Example: 46584 - without this cooldown (which should be set always when pet is loaded) isn't set clientside
    // TODO: pets should be summoned from real cast instead of just faking it?
    if (summon_spell_id)
    {
        WorldPacket data(SMSG_SPELL_GO, (8+8+4+4+2));
        data.append(owner->GetPackGUID());
        data.append(owner->GetPackGUID());
        data << uint8(0);
        data << uint32(summon_spell_id);
        data << uint32(256); // CAST_FLAG_UNKNOWN3
        data << uint32(0);
        owner->SendMessageToSet(&data, true);
    }

	// do it as early as possible!
	pet->InitTalentForLevel();                                   // set original talents points before spell loading
	if (!is_temporary_summoned)
		pet->GetCharmInfo()->InitPetActionBar();

    map->AddToMap(pet->ToCreature(), true);
    if (pet->getPetType() == SUMMON_PET && !current)              //all (?) summon pets come with full health when called, but not when they are current
        pet->SetPower(POWER_MANA, pet->GetMaxPower(POWER_MANA));
    else
    {
        pet->SetHealth(savedhealth > pet->GetMaxHealth() ? pet->GetMaxHealth() : savedhealth);
        pet->SetPower(POWER_MANA, savedmana > pet->GetMaxPower(POWER_MANA) ? pet->GetMaxPower(POWER_MANA) : savedmana);
    }

	pet->SetAsynchLoadType(asynchLoadType);

	// xinef: clear any old result
	if (_loadPetFromDBSecondCallback.ready())
	{
		SQLQueryHolder* param;
		_loadPetFromDBSecondCallback.get(param);
		delete param;
	}
	_loadPetFromDBSecondCallback.cancel();

    _loadPetFromDBSecondCallback = CharacterDatabase.DelayQueryHolder((SQLQueryHolder*)holder);
	return PET_LOAD_OK;
}
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
示例#14
0
void WorldSession::HandleStableSwapPet( WorldPacket & recv_data )
{
    sLog.outDetail("WORLD: Recv CMSG_STABLE_SWAP_PET.");
    uint64 npcGUID;
    uint32 pet_number;

    recv_data >> npcGUID >> pet_number;

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

    Creature *unit = ObjectAccessor::Instance().GetCreature(*_player, npcGUID);
    if (!unit)
    {
        sLog.outDebug( "WORLD: CMSG_STABLE_SWAP_PET - NO SUCH UNIT! (GUID: %u)", uint32(GUID_LOPART(npcGUID)) );
        return;
    }

    if( unit->IsHostileTo(_player))                         // do not talk with enemies
        return;

    WorldPacket data(SMSG_STABLE_RESULT, 200);              // guess size

    Pet* pet = _player->GetPet();

    if(!pet)
        return;

    if(!pet->GetUInt32Value(UNIT_FIELD_PETNUMBER))
        return;

    QueryResult *result;

    result = sDatabase.PQuery("SELECT `owner`,`slot`,`petnumber`,`entry`,`level`,`loyalty`,`trainpoint` FROM `character_stable` WHERE `owner` = '%u' AND `petnumber` = '%u'",_player->GetGUIDLow(),pet_number);
    if(!result)
    {
        delete result;
        return;
    }

    Field *fields = result->Fetch();

    uint32 slot = fields[1].GetUInt32();
    uint32 petentry = fields[3].GetUInt32();
    delete result;

    // move alive pet to slot
    if(pet->isAlive())
    {
        sDatabase.BeginTransaction();
        sDatabase.PExecute("DELETE FROM `character_stable` WHERE `owner` = '%u' AND `slot` = '%u'", _player->GetGUIDLow(),slot);
        sDatabase.PExecute("INSERT INTO `character_stable` (`owner`,`slot`,`petnumber`,`entry`,`level`,`loyalty`,`trainpoint`) VALUES (%u,%u,%u,%u,%u,%u,%u)",
            _player->GetGUIDLow(),slot,pet->GetUInt32Value(UNIT_FIELD_PETNUMBER),pet->GetEntry(),pet->getLevel(),pet->getloyalty(),pet->getUsedTrainPoint());
        sDatabase.CommitTransaction();
        _player->RemovePet(pet,PET_SAVE_AS_STORED);
    }
    // delele dead pet and free slot
    else
    {
        sDatabase.PExecute("UPDATE `character_stable` SET `petnumber` = '0',`entry` = '0',`level` = '0',`loyalty` = '0',`trainpoint` = '0' WHERE `owner` = '%u' AND `slot` = '%u'",_player->GetGUIDLow(), slot);
        _player->RemovePet(pet,PET_SAVE_AS_DELETED);
    }

    // summon unstabled pet
    Pet *newpet = new Pet(_player->getClass()==CLASS_HUNTER?HUNTER_PET:SUMMON_PET);
    if(!newpet->LoadPetFromDB(_player,petentry))
    {
        delete newpet;
        data << uint8(0x06);
    }
    else
        data << uint8(0x09);
    SendPacket(&data);
}
示例#15
0
void WorldSession::HandleStablePet( WorldPacket & recv_data )
{
    sLog.outDetail("WORLD: Recv CMSG_STABLE_PET not dispose.");
    uint64 npcGUID;

    recv_data >> npcGUID;

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

    Creature *unit = ObjectAccessor::Instance().GetCreature(*_player, npcGUID);
    if (!unit)
    {
        sLog.outDebug( "WORLD: CMSG_STABLE_PET - NO SUCH UNIT! (GUID: %u)", uint32(GUID_LOPART(npcGUID)) );
        return;
    }

    if( unit->IsHostileTo(_player))                         // do not talk with enemies
        return;

    Pet *pet = _player->GetPet();

    WorldPacket data(SMSG_STABLE_RESULT, 200);              // guess size

    // can't place in stable dead pet
    if(!pet||!pet->isAlive())
    {
        data << uint8(0x06);
        SendPacket(&data);
        return;
    }

    if(!pet->GetUInt32Value(UNIT_FIELD_PETNUMBER))
        return;

    QueryResult *result;
    bool flag = false;

    result = sDatabase.PQuery("SELECT `owner`,`slot`,`petnumber` FROM `character_stable` WHERE `owner` = '%u' ORDER BY `slot` ",_player->GetGUIDLow());
    if(result)
    {
        do
        {
            Field *fields = result->Fetch();

            uint32 slot = fields[1].GetUInt32();
            if(fields[2].GetUInt32())
                continue;
            else if(pet->GetUInt32Value(UNIT_FIELD_PETNUMBER) == fields[2].GetUInt32())
                break;
            else if( slot == 1 || slot == 2)
            {
                sDatabase.BeginTransaction();
                sDatabase.PExecute("DELETE FROM `character_stable` WHERE `owner` = '%u' AND `slot` = '%u'", _player->GetGUIDLow(),slot);
                sDatabase.PExecute("INSERT INTO `character_stable` (`owner`,`slot`,`petnumber`,`entry`,`level`,`loyalty`,`trainpoint`) VALUES (%u,%u,%u,%u,%u,%u,%u)",
                    _player->GetGUIDLow(),slot,pet->GetUInt32Value(UNIT_FIELD_PETNUMBER),pet->GetEntry(),pet->getLevel(),pet->getloyalty(),pet->getUsedTrainPoint());
                sDatabase.CommitTransaction();
                data << uint8(0x08);
                flag = true;
                _player->RemovePet(pet,PET_SAVE_AS_STORED);
                break;
            }
        }while( result->NextRow() );
    }
    delete result;

    if(!flag)
        data << uint8(0x06);
    SendPacket(&data);
}
示例#16
0
void WorldSession::SendStablePet(uint64 guid )
{
    sLog.outDetail("WORLD: Recv MSG_LIST_STABLED_PETS Send.");

    WorldPacket data(MSG_LIST_STABLED_PETS, 200);           // guess size
    data << uint64 ( guid );

    QueryResult *result,*result_1;
    uint8 max_slot = 0;
    uint8 num = 0;

    result_1 = sDatabase.PQuery("SELECT `slot`,`petnumber` FROM `character_stable` WHERE `owner` = '%u'",_player->GetGUIDLow());
    if(result_1)
    {
        do
        {
            Field *fields = result_1->Fetch();

            uint8 cur_slot = fields[0].GetUInt32();
            if(max_slot < cur_slot)
                max_slot = cur_slot;
            if(fields[1].GetUInt32())
                num++;
        }while( result_1->NextRow() );
    }
    delete result_1;

    Pet *pet = _player->GetPet();

    // count only alive pet
    if(pet && pet->isAlive())
        num++;

    data << uint8(num) << uint8(max_slot);

    // not let move dead pet in slot
    if(pet && pet->isAlive())
    {
        if(!pet->GetUInt32Value(UNIT_FIELD_PETNUMBER))
            return;
                                                            // petnumber
        data << uint32(pet->GetUInt32Value(UNIT_FIELD_PETNUMBER));
        data << uint32(pet->GetEntry());
        data << uint32(pet->getLevel());
        //data << cinfo->Name;                                                    // petname
        data << uint8(0x00);
        data << uint32(pet->getloyalty());                  // loyalty
        data << uint8(0x01);                                // slot
    }

    result = sDatabase.PQuery("SELECT `owner`,`slot`,`petnumber`,`entry`,`level`,`loyalty`,`trainpoint` FROM `character_stable` WHERE `owner` = '%u'",_player->GetGUIDLow());

    if(result)
    {
        do
        {
            Field *fields = result->Fetch();
            uint32 petentry = fields[3].GetUInt32();
            if(petentry)
            {
                CreatureInfo const *cinfo = objmgr.GetCreatureTemplate(petentry);
                data << uint32(fields[2].GetUInt32());      // petnumber
                data << uint32(petentry);
                data << uint32(fields[4].GetUInt32());
                data << cinfo->Name;
                data << uint32(fields[5].GetUInt32());      // loyalty
                data << uint8(fields[1].GetUInt32()+1);     // slot
            }
        }while( result->NextRow() );
    }
    delete result;
    SendPacket(&data);
}