/** * NeedGroupBuff() * return boolean Returns true if more than two targets in the bot's group need the group buff. * * params:groupBuffSpellId uint32 the spell ID of the group buff like Arcane Brillance * params:singleBuffSpellId uint32 the spell ID of the single target buff equivalent of the group buff like Arcane Intellect for group buff Arcane Brillance * return false if false is returned, the bot is expected to perform a buff check for the single target buff of the group buff. * */ bool PlayerbotClassAI::NeedGroupBuff(uint32 groupBuffSpellId, uint32 singleBuffSpellId) { if (!m_bot) return false; uint8 numberOfGroupTargets = 0; // Check group players to avoid using regeant and mana with an expensive group buff // when only two players or less need it if (m_bot->GetGroup()) { Group::MemberSlotList const& groupSlot = m_bot->GetGroup()->GetMemberSlots(); for (Group::member_citerator itr = groupSlot.begin(); itr != groupSlot.end(); itr++) { Player *groupMember = sObjectMgr.GetPlayer(itr->guid); if (!groupMember || !groupMember->isAlive()) continue; // Check if group member needs buff if (!groupMember->HasAura(groupBuffSpellId, EFFECT_INDEX_0) && !groupMember->HasAura(singleBuffSpellId, EFFECT_INDEX_0)) numberOfGroupTargets++; // Don't forget about pet Pet * pet = groupMember->GetPet(); if (pet && !pet->HasAuraType(SPELL_AURA_MOD_UNATTACKABLE) && (pet->HasAura(groupBuffSpellId, EFFECT_INDEX_0) || pet->HasAura(singleBuffSpellId, EFFECT_INDEX_0))) numberOfGroupTargets++; } // treshold set to 2 targets because beyond that value, the group buff cost is cheaper in mana if (numberOfGroupTargets < 3) return false; // In doubt, buff everyone return true; } else return false; // no group, no group buff }
void PlayerbotHunterAI::DoNonCombatActions() { PlayerbotAI *ai = GetAI(); if (!ai) return; Player * m_bot = GetPlayerBot(); if (!m_bot) return; // reset ranged combat state if (!m_rangedCombat) m_rangedCombat = true; // buff group if (TRUESHOT_AURA > 0) (!m_bot->HasAura(TRUESHOT_AURA, EFFECT_INDEX_0) && ai->CastSpell (TRUESHOT_AURA, *m_bot)); // buff myself if (ASPECT_OF_THE_HAWK > 0) (!m_bot->HasAura(ASPECT_OF_THE_HAWK, EFFECT_INDEX_0) && ai->CastSpell (ASPECT_OF_THE_HAWK, *m_bot)); // mana check if (m_bot->getStandState() != UNIT_STAND_STATE_STAND) m_bot->SetStandState(UNIT_STAND_STATE_STAND); Item* pItem = ai->FindDrink(); Item* fItem = ai->FindBandage(); if (pItem != NULL && ai->GetManaPercent() < 30) { ai->TellMaster("I could use a drink."); ai->UseItem(pItem); return; } // hp check if (m_bot->getStandState() != UNIT_STAND_STATE_STAND) m_bot->SetStandState(UNIT_STAND_STATE_STAND); pItem = ai->FindFood(); if (pItem != NULL && ai->GetHealthPercent() < 30) { ai->TellMaster("I could use some food."); ai->UseItem(pItem); return; } else if (pItem == NULL && fItem != NULL && !m_bot->HasAura(RECENTLY_BANDAGED, EFFECT_INDEX_0) && ai->GetHealthPercent() < 70) { ai->TellMaster("I could use first aid."); ai->UseItem(fItem); 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 && ai->CastSpell(PET_SUMMON, *m_bot)) ai->TellMaster("summoning pet."); else { m_petSummonFailed = true; ai->TellMaster("summon pet failed!"); } } else if (pet->getDeathState() != ALIVE) { // revive pet if (PET_REVIVE > 0 && ai->GetManaPercent() >= 80 && ai->CastSpell(PET_REVIVE, *m_bot)) ai->TellMaster("reviving pet."); } else if (((float) pet->GetHealth() / (float) pet->GetMaxHealth()) < 0.5f) { // heal pet when health lower 50% if (PET_MEND > 0 && !pet->getDeathState() != ALIVE && !pet->HasAura(PET_MEND, EFFECT_INDEX_0) && ai->GetManaPercent() >= 13 && ai->CastSpell(PET_MEND, *m_bot)) 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, 51284, 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, NULL, NULL, true); // feed pet ai->TellMaster("feeding pet."); 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, 51284, 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, NULL, NULL, true); // feed pet ai->TellMaster("feeding pet."); ai->SetIgnoreUpdateTime(10); return; } } } } if (pet->HasAura(PET_MEND, EFFECT_INDEX_0) && !pet->HasAura(PET_FEED, EFFECT_INDEX_0)) ai->TellMaster("..no pet food!"); ai->SetIgnoreUpdateTime(7); } } } // end DoNonCombatActions
void PlayerbotHunterAI::DoNextCombatManeuver(Unit *pTarget) { PlayerbotAI* ai = GetAI(); if (!ai) return; switch (ai->GetScenarioType()) { case PlayerbotAI::SCENARIO_DUEL: ai->CastSpell(RAPTOR_STRIKE); return; default: break; } // ------- Non Duel combat ---------- // Hunter Player *m_bot = GetPlayerBot(); Unit* pVictim = pTarget->getVictim(); // check for pet and heal if neccessary Pet *pet = m_bot->GetPet(); if ((pet) && (((float) pet->GetHealth() / (float) pet->GetMaxHealth()) < 0.5f) && (PET_MEND > 0 && !pet->getDeathState() != ALIVE && pVictim != m_bot && !pet->HasAura(PET_MEND, EFFECT_INDEX_0) && ai->GetManaPercent() >= 13 && ai->CastSpell(PET_MEND, *m_bot))) { ai->TellMaster("healing pet."); return; } else if ((pet) && (INTIMIDATION > 0 && pVictim == pet && !pet->HasAura(INTIMIDATION, EFFECT_INDEX_0) && ai->CastSpell(INTIMIDATION, *m_bot))) //ai->TellMaster( "casting intimidation." ); // if pet has aggro :) return; // racial traits if (m_bot->getRace() == RACE_ORC && !m_bot->HasAura(BLOOD_FURY, EFFECT_INDEX_0)) ai->CastSpell(BLOOD_FURY, *m_bot); //ai->TellMaster( "Blood Fury." ); else if (m_bot->getRace() == RACE_TROLL && !m_bot->HasAura(BERSERKING, EFFECT_INDEX_0)) ai->CastSpell(BERSERKING, *m_bot); //ai->TellMaster( "Berserking." ); // check if ranged combat is possible (set m_rangedCombat and switch auras float dist = m_bot->GetCombatDistance(pTarget); if ((dist <= ATTACK_DISTANCE || !m_bot->GetUInt32Value(PLAYER_AMMO_ID)) && m_rangedCombat) { // switch to melee combat (target in melee range, out of ammo) m_rangedCombat = false; if (!m_bot->GetUInt32Value(PLAYER_AMMO_ID)) ai->TellMaster("Out of ammo!"); // become monkey (increases dodge chance)... (ASPECT_OF_THE_MONKEY > 0 && !m_bot->HasAura(ASPECT_OF_THE_MONKEY, EFFECT_INDEX_0) && ai->CastSpell(ASPECT_OF_THE_MONKEY, *m_bot)); } else if (dist > ATTACK_DISTANCE && !m_rangedCombat) { // switch to ranged combat m_rangedCombat = true; // increase ranged attack power... (ASPECT_OF_THE_HAWK > 0 && !m_bot->HasAura(ASPECT_OF_THE_HAWK, EFFECT_INDEX_0) && ai->CastSpell(ASPECT_OF_THE_HAWK, *m_bot)); } else if (m_rangedCombat && !m_bot->HasAura(ASPECT_OF_THE_HAWK, EFFECT_INDEX_0)) // check if we have hawk aspect in ranged combat (ASPECT_OF_THE_HAWK > 0 && ai->CastSpell(ASPECT_OF_THE_HAWK, *m_bot)); else if (!m_rangedCombat && !m_bot->HasAura(ASPECT_OF_THE_MONKEY, EFFECT_INDEX_0)) // check if we have monkey aspect in melee combat (ASPECT_OF_THE_MONKEY > 0 && ai->CastSpell(ASPECT_OF_THE_MONKEY, *m_bot)); // activate auto shot if (AUTO_SHOT > 0 && m_rangedCombat && !m_bot->FindCurrentSpellBySpellId(AUTO_SHOT)) ai->CastSpell(AUTO_SHOT, *pTarget); //ai->TellMaster( "started auto shot." ); else if (AUTO_SHOT > 0 && m_bot->FindCurrentSpellBySpellId(AUTO_SHOT)) m_bot->InterruptNonMeleeSpells(true, AUTO_SHOT); //ai->TellMaster( "stopped auto shot." ); // damage spells std::ostringstream out; if (m_rangedCombat) { out << "Case Ranged"; if (HUNTERS_MARK > 0 && ai->GetManaPercent() >= 3 && !pTarget->HasAura(HUNTERS_MARK, EFFECT_INDEX_0) && ai->CastSpell(HUNTERS_MARK, *pTarget)) out << " > Hunter's Mark"; else if (RAPID_FIRE > 0 && ai->GetManaPercent() >= 3 && !m_bot->HasAura(RAPID_FIRE, EFFECT_INDEX_0) && ai->CastSpell(RAPID_FIRE, *m_bot)) out << " > Rapid Fire"; else if (MULTI_SHOT > 0 && ai->GetManaPercent() >= 13 && ai->GetAttackerCount() >= 3 && ai->CastSpell(MULTI_SHOT, *pTarget)) out << " > Multi-Shot"; else if (ARCANE_SHOT > 0 && ai->GetManaPercent() >= 7 && ai->CastSpell(ARCANE_SHOT, *pTarget)) out << " > Arcane Shot"; else if (CONCUSSIVE_SHOT > 0 && ai->GetManaPercent() >= 6 && !pTarget->HasAura(CONCUSSIVE_SHOT, EFFECT_INDEX_0) && ai->CastSpell(CONCUSSIVE_SHOT, *pTarget)) out << " > Concussive Shot"; else if (EXPLOSIVE_SHOT > 0 && ai->GetManaPercent() >= 10 && !pTarget->HasAura(EXPLOSIVE_SHOT, EFFECT_INDEX_0) && ai->CastSpell(EXPLOSIVE_SHOT, *pTarget)) out << " > Explosive Shot"; else if (VIPER_STING > 0 && ai->GetManaPercent() >= 8 && pTarget->GetPower(POWER_MANA) > 0 && ai->GetManaPercent() < 70 && !pTarget->HasAura(VIPER_STING, EFFECT_INDEX_0) && ai->CastSpell(VIPER_STING, *pTarget)) out << " > Viper Sting"; else if (SERPENT_STING > 0 && ai->GetManaPercent() >= 13 && !pTarget->HasAura(SERPENT_STING, EFFECT_INDEX_0) && !pTarget->HasAura(SCORPID_STING, EFFECT_INDEX_0) && !pTarget->HasAura(VIPER_STING, EFFECT_INDEX_0) && ai->CastSpell(SERPENT_STING, *pTarget)) out << " > Serpent Sting"; else if (SCORPID_STING > 0 && ai->GetManaPercent() >= 11 && !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) && ai->CastSpell(SCORPID_STING, *pTarget)) out << " > Scorpid Sting"; else if (CHIMERA_SHOT > 0 && ai->GetManaPercent() >= 12 && ai->CastSpell(CHIMERA_SHOT, *pTarget)) out << " > Chimera Shot"; else if (VOLLEY > 0 && ai->GetManaPercent() >= 24 && ai->GetAttackerCount() >= 3 && ai->CastSpell(VOLLEY, *pTarget)) out << " > Volley"; else if (BLACK_ARROW > 0 && ai->GetManaPercent() >= 6 && !pTarget->HasAura(BLACK_ARROW, EFFECT_INDEX_0) && ai->CastSpell(BLACK_ARROW, *pTarget)) out << " > Black Arrow"; else if (AIMED_SHOT > 0 && ai->GetManaPercent() >= 12 && ai->CastSpell(AIMED_SHOT, *pTarget)) out << " > Aimed Shot"; else if (STEADY_SHOT > 0 && ai->GetManaPercent() >= 5 && ai->CastSpell(STEADY_SHOT, *pTarget)) out << " > Steady Shot"; else if (KILL_SHOT > 0 && ai->GetManaPercent() >= 7 && pTarget->GetHealth() < pTarget->GetMaxHealth() * 0.2 && ai->CastSpell(KILL_SHOT, *pTarget)) out << " > Kill Shot!"; else out << " NONE!"; } else { out << "Case Melee"; if (RAPTOR_STRIKE > 0 && ai->GetManaPercent() >= 6 && ai->CastSpell(RAPTOR_STRIKE, *pTarget)) out << " > Raptor Strike"; else if (EXPLOSIVE_TRAP > 0 && ai->GetManaPercent() >= 27 && !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) && ai->CastSpell(EXPLOSIVE_TRAP, *pTarget)) out << " > Explosive Trap"; else if (WING_CLIP > 0 && ai->GetManaPercent() >= 6 && !pTarget->HasAura(WING_CLIP, EFFECT_INDEX_0) && ai->CastSpell(WING_CLIP, *pTarget)) out << " > Wing Clip"; else if (IMMOLATION_TRAP > 0 && ai->GetManaPercent() >= 13 && !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) && ai->CastSpell(IMMOLATION_TRAP, *pTarget)) out << " > Immolation Trap"; else if (MONGOOSE_BITE > 0 && ai->GetManaPercent() >= 4 && ai->CastSpell(MONGOOSE_BITE, *pTarget)) out << " > Mongoose Bite"; else if (FROST_TRAP > 0 && ai->GetManaPercent() >= 2 && !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) && ai->CastSpell(FROST_TRAP, *pTarget)) out << " > Frost Trap"; 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) && ai->CastSpell(ARCANE_TRAP, *pTarget)) out << " > Arcane Trap"; else if (DETERRENCE > 0 && pVictim == m_bot && m_bot->GetHealth() < m_bot->GetMaxHealth() * 0.5 && !m_bot->HasAura(DETERRENCE, EFFECT_INDEX_0) && ai->CastSpell(DETERRENCE, *m_bot)) out << " > Deterrence"; else if (m_bot->getRace() == RACE_TAUREN && !pTarget->HasAura(WAR_STOMP, EFFECT_INDEX_0) && ai->CastSpell(WAR_STOMP, *pTarget)) out << " > War Stomp"; else if (m_bot->getRace() == RACE_DWARF && m_bot->HasAuraState(AURA_STATE_DEADLY_POISON) && ai->CastSpell(STONEFORM, *m_bot)) out << " > Stoneform"; else if (m_bot->getRace() == RACE_NIGHTELF && pVictim == m_bot && ai->GetHealthPercent() < 25 && !m_bot->HasAura(SHADOWMELD, EFFECT_INDEX_0) && ai->CastSpell(SHADOWMELD, *m_bot)) out << " > Shadowmeld"; else if ((pet && !pet->getDeathState() != ALIVE) && (MISDIRECTION > 0 && pVictim == m_bot && !m_bot->HasAura(MISDIRECTION, EFFECT_INDEX_0) && ai->GetManaPercent() >= 9 && ai->CastSpell(MISDIRECTION, *pet))) out << " > Misdirection"; // give threat to pet /*else if( FREEZING_TRAP>0 && ai->GetManaPercent()>=5 && !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) && 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) && ai->CastSpell(BEAR_TRAP,*pTarget) ) out << " > Bear Trap"; // this was just too annoying :) else if( DISENGAGE>0 && pVictim && ai->GetManaPercent()>=5 && ai->CastSpell(DISENGAGE,*pTarget) ) out << " > Disengage!"; // attempt to return to ranged combat*/ else out << " NONE!"; } if (ai->GetManager()->m_confDebugWhisper) ai->TellMaster(out.str().c_str()); } // end DoNextCombatManeuver
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 PlayerbotHunterAI::DoNonCombatActions() { PlayerbotAI *ai = GetAI(); Player * m_bot = GetPlayerBot(); Player* m_master = ai->GetLeader(); static const uint32 MinorGlyphs[] = {57903, 57866, 57870}; // feigh death - revive pet - healing pet static const uint32 SurvivalMajorGlyphs[] = {56832, 56826, 63066}; // serpent sting - steady shot - explosive shot for (uint32 i = 0; i < 3; i++) { if (!m_bot->HasSpell(MinorGlyphs[i])) m_bot->learnSpell(MinorGlyphs[i], true); if (!m_bot->HasSpell(SurvivalMajorGlyphs[i])) m_bot->learnSpell(SurvivalMajorGlyphs[i], true); } if (!m_bot->HasAura(TRUESHOT_AURA, EFFECT_INDEX_0)) ai->CastSpell(TRUESHOT_AURA, m_bot); if (!m_bot->HasAura(ASPECT_OF_THE_VIPER, EFFECT_INDEX_0) && ai->GetManaPercent() < 90 && ai->CastSpell(ASPECT_OF_THE_VIPER, m_bot)) return; else if (!m_bot->HasAura(ASPECT_OF_THE_DRAGONHAWK, EFFECT_INDEX_0) && ai->GetManaPercent() >= 90 && ai->CastSpell(ASPECT_OF_THE_DRAGONHAWK, m_bot)) return; // reset ranged combat state if (!m_rangedCombat) m_rangedCombat = true; // 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 && ai->CastSpell(PET_SUMMON, m_bot)) { } else { m_petSummonFailed = true; } } else if (pet->getDeathState() != ALIVE) { // revive pet if (PET_REVIVE > 0 && ai->GetManaPercent() >= 80 && ai->CastSpell(PET_REVIVE, m_bot)) { } } else if (((float) pet->GetHealth() / (float) pet->GetMaxHealth()) < 0.5f) { // heal pet when health lower 50% if (PET_MEND > 0 && !pet->getDeathState() != ALIVE && !pet->HasAura(PET_MEND, EFFECT_INDEX_0) && ai->GetManaPercent() >= 13 && ai->CastSpell(PET_MEND, m_bot)) { } } 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 { caster->CastSpell(caster, 51284, 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, NULL, NULL, true); // feed pet 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 { caster->CastSpell(caster, 51284, 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, NULL, NULL, true); // feed pet ai->SetIgnoreUpdateTime(10); return; } } } } if (pet->HasAura(PET_MEND, EFFECT_INDEX_0) && !pet->HasAura(PET_FEED, EFFECT_INDEX_0)) ai->SetIgnoreUpdateTime(7); } } }
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
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
void PlayerbotHunterAI::DoNonCombatActions() { PlayerbotAI *ai = GetAI(); if (!ai) return; Player * m_bot = GetPlayerBot(); if (!m_bot) return; // reset ranged combat state if (!m_rangedCombat) m_rangedCombat = true; // buff group if (TRUESHOT_AURA > 0) (!m_bot->HasAura(TRUESHOT_AURA, EFFECT_INDEX_0) && ai->CastSpell (TRUESHOT_AURA, *m_bot)); // buff myself if (ASPECT_OF_THE_HAWK > 0) (!m_bot->HasAura(ASPECT_OF_THE_HAWK, EFFECT_INDEX_0) && ai->CastSpell (ASPECT_OF_THE_HAWK, *m_bot)); // mana check if (m_bot->getStandState() != UNIT_STAND_STATE_STAND) m_bot->SetStandState(UNIT_STAND_STATE_STAND); Item* pItem = ai->FindDrink(); Item* fItem = ai->FindBandage(); if (pItem != NULL && ai->GetManaPercent() < 30) { ai->TellMaster("I could use a drink."); ai->UseItem(pItem); return; } // hp check if (m_bot->getStandState() != UNIT_STAND_STATE_STAND) m_bot->SetStandState(UNIT_STAND_STATE_STAND); pItem = ai->FindFood(); if (pItem != NULL && ai->GetHealthPercent() < 30) { ai->TellMaster("I could use some food."); ai->UseItem(pItem); return; } else if (pItem == NULL && fItem != NULL && !m_bot->HasAura(RECENTLY_BANDAGED, EFFECT_INDEX_0) && ai->GetHealthPercent() < 70) { ai->TellMaster("I could use first aid."); ai->UseItem(fItem); return; } else if (pItem == NULL && fItem == NULL && m_bot->getRace() == RACE_DRAENEI && !m_bot->HasAura(GIFT_OF_THE_NAARU, EFFECT_INDEX_0) && ai->GetHealthPercent() < 70) { ai->TellMaster("I'm casting gift of the naaru."); ai->CastSpell(GIFT_OF_THE_NAARU, *m_bot); 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 && ai->CastSpell(PET_SUMMON, *m_bot)) ai->TellMaster("summoning pet."); else { m_petSummonFailed = true; ai->TellMaster("summon pet failed!"); } } else if (pet->getDeathState() != ALIVE) { // revive pet if (PET_REVIVE > 0 && ai->GetManaPercent() >= 80 && ai->CastSpell(PET_REVIVE, *m_bot)) ai->TellMaster("reviving pet."); } else if (((float) pet->GetHealth() / (float) pet->GetMaxHealth()) < 0.5f) { // heal pet when health lower 50% if (PET_MEND > 0 && !pet->getDeathState() != ALIVE && !pet->HasAura(PET_MEND, EFFECT_INDEX_0) && ai->GetManaPercent() >= 13 && ai->CastSpell(PET_MEND, *m_bot)) ai->TellMaster("healing pet."); } } } // end DoNonCombatActions
void PlayerbotDeathKnightAI::DoNextCombatManeuver(Unit *pTarget) { PlayerbotAI* ai = GetAI(); if (!ai) return; switch (ai->GetScenarioType()) { case PlayerbotAI::SCENARIO_DUEL: ai->CastSpell(PLAGUE_STRIKE); return; } // ------- Non Duel combat ---------- //ai->SetMovementOrder( PlayerbotAI::MOVEMENT_FOLLOW, GetMaster() ); // dont want to melee mob // DK Attacks: Unholy, Frost & Blood // damage spells ai->SetInFront( pTarget );//<--- Player *m_bot = GetPlayerBot(); Unit* pVictim = pTarget->getVictim(); Pet *pet = m_bot->GetPet(); float dist = m_bot->GetDistance( pTarget ); std::ostringstream out; switch (SpellSequence) { case SPELL_DK_UNHOLY: if (UNHOLY_PRESENCE > 0) (!m_bot->HasAura(UNHOLY_PRESENCE, 0) && !m_bot->HasAura(BLOOD_PRESENCE, 0) && !m_bot->HasAura(FROST_PRESENCE, 0) && ai->CastSpell (UNHOLY_PRESENCE, *m_bot)); // check for BONE_SHIELD in combat if (BONE_SHIELD > 0) (!m_bot->HasAura(BONE_SHIELD, 0) && !m_bot->HasAura(ARMY_OF_THE_DEAD, 0) && ai->CastSpell (BONE_SHIELD, *m_bot)); if (ARMY_OF_THE_DEAD > 0 && ai->GetAttackerCount()>=5 && LastSpellUnholyDK < 1) { ai->CastSpell(ARMY_OF_THE_DEAD); out << " summoning Army of the Dead!"; if (ARMY_OF_THE_DEAD > 0 && m_bot->HasAura(ARMY_OF_THE_DEAD, 0)) ai->SetIgnoreUpdateTime(7); SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (PLAGUE_STRIKE > 0 && !pTarget->HasAura(PLAGUE_STRIKE, 0) && LastSpellUnholyDK < 2) { ai->CastSpell(PLAGUE_STRIKE, *pTarget); out << " Plague Strike"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (DEATH_GRIP > 0 && !pTarget->HasAura(DEATH_GRIP, 0) && LastSpellUnholyDK < 3) { ai->CastSpell(DEATH_GRIP, *pTarget); out << " Death Grip"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (DEATH_COIL > 0 && LastSpellUnholyDK < 4 && ai->GetRunicPower() >= 40) { ai->CastSpell(DEATH_COIL, *pTarget); out << " Death Coil"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (DEATH_STRIKE > 0 && !pTarget->HasAura(DEATH_STRIKE, 0) && LastSpellUnholyDK < 5) { ai->CastSpell(DEATH_STRIKE, *pTarget); out << " Death Strike"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (UNHOLY_BLIGHT > 0 && !pTarget->HasAura(UNHOLY_BLIGHT, 0) && LastSpellUnholyDK < 6) { ai->CastSpell(UNHOLY_BLIGHT); out << " Unholy Blight"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (SCOURGE_STRIKE > 0 && LastSpellUnholyDK < 7) { ai->CastSpell(SCOURGE_STRIKE, *pTarget); out << " Scourge Strike"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (DEATH_AND_DECAY > 0 && ai->GetAttackerCount()>=3 && dist <= ATTACK_DISTANCE && !pTarget->HasAura(DEATH_AND_DECAY, 0) && LastSpellUnholyDK < 8) { ai->CastSpell(DEATH_AND_DECAY); out << " Death and Decay"; ai->SetIgnoreUpdateTime(1); SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (SUMMON_GARGOYLE > 0 && !m_bot->HasAura(ARMY_OF_THE_DEAD, 0) && !pTarget->HasAura(SUMMON_GARGOYLE, 0) && LastSpellUnholyDK < 9 && ai->GetRunicPower() >= 60) { ai->CastSpell(SUMMON_GARGOYLE, *pTarget); out << " summoning Gargoyle"; ai->SetIgnoreUpdateTime(2); SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (CORPSE_EXPLOSION > 0 && dist <= ATTACK_DISTANCE && LastSpellUnholyDK < 10) { ai->CastSpell(CORPSE_EXPLOSION, *pTarget); out << " Corpse Explosion"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (ANTI_MAGIC_SHELL > 0 && pTarget->IsNonMeleeSpellCasted(true) && !m_bot->HasAura(ANTI_MAGIC_SHELL, 0) && LastSpellUnholyDK < 11 && ai->GetRunicPower() >= 20) { ai->CastSpell(ANTI_MAGIC_SHELL, *m_bot); out << " Anti-Magic Shell"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (ANTI_MAGIC_ZONE > 0 && pTarget->IsNonMeleeSpellCasted(true) && !m_bot->HasAura(ANTI_MAGIC_SHELL, 0) && LastSpellUnholyDK < 12) { ai->CastSpell(ANTI_MAGIC_ZONE, *m_bot); out << " Anti-Magic Zone"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if(( !pet ) && (RAISE_DEAD > 0 && !m_bot->HasAura(ARMY_OF_THE_DEAD, 0) && LastSpellUnholyDK < 13)) { ai->CastSpell(RAISE_DEAD); out << " summoning Ghoul"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if(( pet ) && (GHOUL_FRENZY > 0 && pVictim == pet && !pet->HasAura(GHOUL_FRENZY, 0) && LastSpellUnholyDK < 14)) { ai->CastSpell(GHOUL_FRENZY, *pet); out << " casting Ghoul Frenzy on pet"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK +1; break; } else if (LastSpellUnholyDK > 15) { LastSpellUnholyDK = 0; SpellSequence = SPELL_DK_FROST; break; } LastSpellUnholyDK = 0; case SPELL_DK_FROST: if (FROST_PRESENCE > 0) (!m_bot->HasAura(FROST_PRESENCE, 0) && !m_bot->HasAura(BLOOD_PRESENCE, 0) && !m_bot->HasAura(UNHOLY_PRESENCE, 0) && ai->CastSpell (FROST_PRESENCE, *m_bot)); if (DEATHCHILL > 0) (!m_bot->HasAura(DEATHCHILL, 0) && !m_bot->HasAura(KILLING_MACHINE, 0) && ai->CastSpell (DEATHCHILL, *m_bot)); else if (KILLING_MACHINE > 0) (!m_bot->HasAura(KILLING_MACHINE, 0) && !m_bot->HasAura(DEATHCHILL, 0) && ai->CastSpell (KILLING_MACHINE, *m_bot)); if (ICY_TOUCH > 0 && !pTarget->HasAura(ICY_TOUCH, 0) && LastSpellFrostDK < 1) { ai->CastSpell(ICY_TOUCH, *pTarget); out << " Icy Touch"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (OBLITERATE > 0 && LastSpellFrostDK < 2) { ai->CastSpell(OBLITERATE, *pTarget); out << " Obliterate"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (FROST_STRIKE > 0 && LastSpellFrostDK < 3 && ai->GetRunicPower() >= 40) { ai->CastSpell(FROST_STRIKE, *pTarget); out << " Frost Strike"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (HOWLING_BLAST > 0 && ai->GetAttackerCount()>=3 && LastSpellFrostDK < 4) { ai->CastSpell(HOWLING_BLAST, *pTarget); out << " Howling Blast"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (CHAINS_OF_ICE > 0 && !pTarget->HasAura(CHAINS_OF_ICE, 0) && LastSpellFrostDK < 5) { ai->CastSpell(CHAINS_OF_ICE, *pTarget); out << " Chains of Ice"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (RUNE_STRIKE > 0 && LastSpellFrostDK < 6 && ai->GetRunicPower() >= 20) { ai->CastSpell(RUNE_STRIKE, *pTarget); out << " Rune Strike"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (ICY_CLUTCH > 0 && !pTarget->HasAura(ICY_CLUTCH, 0) && LastSpellFrostDK < 7) { ai->CastSpell(ICY_CLUTCH, *pTarget); out << " Icy Clutch"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (ICEBOUND_FORTITUDE > 0 && ai->GetHealthPercent() < 50 && pVictim == m_bot && !m_bot->HasAura(ICEBOUND_FORTITUDE, 0) && LastSpellFrostDK < 8 && ai->GetRunicPower() >= 20) { ai->CastSpell(ICEBOUND_FORTITUDE, *m_bot); out << " Icebound Fortitude"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (MIND_FREEZE > 0 && pTarget->IsNonMeleeSpellCasted(true) && dist <= ATTACK_DISTANCE && LastSpellFrostDK < 9 && ai->GetRunicPower() >= 20) { ai->CastSpell(MIND_FREEZE, *pTarget); out << " Mind Freeze"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (HUNGERING_COLD > 0 && ai->GetAttackerCount()>=3 && dist <= ATTACK_DISTANCE && LastSpellFrostDK < 10 && ai->GetRunicPower() >= 40) { ai->CastSpell(HUNGERING_COLD, *pTarget); out << " Hungering Cold"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (EMPOWER_WEAPON > 0 && ai->GetRunicPower() < 20 && LastSpellFrostDK < 11) { ai->CastSpell(EMPOWER_WEAPON, *m_bot); out << " Empower Rune Weapon"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (UNBREAKABLE_ARMOR > 0 && !m_bot->HasAura(UNBREAKABLE_ARMOR, 0) && ai->GetHealthPercent() < 70 && pVictim == m_bot && LastSpellFrostDK < 12) { ai->CastSpell(UNBREAKABLE_ARMOR, *m_bot); out << " Unbreakable Armor"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK +1; break; } else if (LastSpellFrostDK > 13) { LastSpellFrostDK = 0; SpellSequence = SPELL_DK_BLOOD; break; } LastSpellFrostDK = 0; case SPELL_DK_BLOOD: if (BLOOD_PRESENCE > 0) (!m_bot->HasAura(BLOOD_PRESENCE, 0) && !m_bot->HasAura(UNHOLY_PRESENCE, 0) && !m_bot->HasAura(FROST_PRESENCE, 0) && ai->CastSpell (BLOOD_PRESENCE, *m_bot)); if (MARK_OF_BLOOD > 0 && !pTarget->HasAura(MARK_OF_BLOOD, 0) && LastSpellBloodDK < 1) { ai->CastSpell(MARK_OF_BLOOD, *pTarget); out << " Mark of Blood"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (BLOOD_STRIKE > 0 && LastSpellBloodDK < 2) { ai->CastSpell(BLOOD_STRIKE, *pTarget); out << " Blood Strike"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (PESTILENCE > 0 && dist <= ATTACK_DISTANCE && ai->GetAttackerCount()>=3 && LastSpellBloodDK < 3) { ai->CastSpell(PESTILENCE, *pTarget); out << " Pestilence"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (STRANGULATE > 0 && !pTarget->HasAura(STRANGULATE, 0) && LastSpellBloodDK < 4) { ai->CastSpell(STRANGULATE, *pTarget); out << " Strangulate"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (BLOOD_BOIL > 0 && ai->GetAttackerCount()>=5 && dist <= ATTACK_DISTANCE && LastSpellBloodDK < 5) { ai->CastSpell(BLOOD_BOIL, *pTarget); out << " Blood Boil"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (HEART_STRIKE > 0 && LastSpellBloodDK < 6) { ai->CastSpell(HEART_STRIKE, *pTarget); out << " Heart Strike"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (VAMPIRIC_BLOOD > 0 && ai->GetHealthPercent() < 70 && !m_bot->HasAura(VAMPIRIC_BLOOD, 0) && LastSpellBloodDK < 7) { ai->CastSpell(VAMPIRIC_BLOOD, *m_bot); out << " Vampiric Blood"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (RUNE_TAP > 0 && ai->GetHealthPercent() < 70 && !m_bot->HasAura(VAMPIRIC_BLOOD, 0) && LastSpellBloodDK < 8) { ai->CastSpell(RUNE_TAP, *m_bot); out << " Rune Tap"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (HYSTERIA > 0 && ai->GetHealthPercent() > 25 && !m_bot->HasAura(HYSTERIA, 0) && LastSpellBloodDK < 9) { ai->CastSpell(HYSTERIA, *m_bot); out << " Hysteria"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (DANCING_WEAPON > 0 && !m_bot->HasAura(DANCING_WEAPON, 0) && ai->GetRunicPower() >= 60 && LastSpellBloodDK < 10) { ai->CastSpell(DANCING_WEAPON, *pTarget); out << " summoning Dancing Rune Weapon"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (DARK_COMMAND > 0 && ai->GetHealthPercent() > 50 && pVictim != m_bot && !pTarget->HasAura(DARK_COMMAND, 0) && dist <= ATTACK_DISTANCE && LastSpellBloodDK < 11) { ai->CastSpell(DARK_COMMAND, *pTarget); out << " Dark Command"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if(( pet ) && (DEATH_PACT > 0 && ai->GetHealthPercent() < 50 && LastSpellBloodDK < 12 && ai->GetRunicPower() >= 40)) { ai->CastSpell(DEATH_PACT, *pet); out << " Death Pact (sacrifice pet)"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK +1; break; } else if (LastSpellBloodDK > 13) { LastSpellBloodDK = 0; SpellSequence = SPELL_DK_UNHOLY; break; } else { LastSpellBloodDK = 0; SpellSequence = SPELL_DK_UNHOLY; } } if( ai->GetManager()->m_confDebugWhisper ) ai->TellMaster( out.str().c_str() ); } // end DoNextCombatManeuver
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
void PlayerbotHunterAI::DoNonCombatActions() { PlayerbotAI *ai = GetAI(); Player *m_bot = GetPlayerBot(); if (!m_bot || !ai || m_bot->isDead()) { return; } //If Casting or Eating/Drinking return if (m_bot->HasUnitState(UNIT_STAT_CASTING)) { return; } if (m_bot->getStandState() == UNIT_STAND_STATE_SIT) { return; } // buff group if (CastSpell(TRUESHOT_AURA, m_bot)) { return; } //mana/hp check //Don't bother with eating, if low on hp, just let it heal themself if (m_bot->getRace() == (uint8) RACE_UNDEAD_PLAYER && ai->GetHealthPercent() < 75 && CastSpell(R_CANNIBALIZE,m_bot)) { return; } if (ai->GetManaPercent() < 20 || ai->GetHealthPercent() < 30) { ai->Feast(); } #pragma region Check Pet // 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 && ai->CastSpell(PET_SUMMON,m_bot) ) ai->TellMaster( "summoning pet." ); else { m_petSummonFailed = true; ai->TellMaster( "summon pet failed!" ); } } else if( pet->getDeathState() != ALIVE ) { // revive pet if( PET_REVIVE>0 && ai->GetManaPercent()>=80 && ai->CastSpell(PET_REVIVE,m_bot) ) ai->TellMaster( "reviving pet." ); } else if( ((float)pet->GetHealth()/(float)pet->GetMaxHealth()) < 0.5f ) { // heal pet when health lower 50% if( PET_MEND>0 && !pet->getDeathState() != ALIVE && !pet->HasAura(PET_MEND,0) && ai->GetManaPercent()>=13 && ai->CastSpell(PET_MEND,m_bot) ) 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 ItemTemplate* const pItemProto = pItem->GetTemplate(); if (!pItemProto ) continue; if(pet->HaveInDiet(pItemProto)) // is pItem in pets diet { //sLog.outDebug("Food for pet: %s",pItemProto->Name1); caster->CastSpell(caster,51284,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,NULL,NULL,true); // feed pet ai->TellMaster( "feeding pet." ); 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 ItemTemplate* const pItemProto = pItem->GetTemplate(); if (!pItemProto ) continue; if(pet->HaveInDiet(pItemProto)) // is pItem in pets diet { //sLog.outDebug("Food for pet: %s",pItemProto->Name1); caster->CastSpell(caster,51284,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,NULL,NULL,true); // feed pet ai->TellMaster( "feeding pet." ); ai->SetIgnoreUpdateTime(10); return; } } } } } if( pet->HasAura(PET_MEND, 0) && !pet->HasAura(PET_FEED, 0)) ai->TellMaster( "..no pet food!" ); ai->SetIgnoreUpdateTime(7); } #pragma endregion } } // end DoNonCombatActions
CombatManeuverReturns PlayerbotDeathKnightAI::DoNextCombatManeuverPVE(Unit *pTarget) { if (!m_ai) return RETURN_NO_ACTION_ERROR; if (!m_bot) return RETURN_NO_ACTION_ERROR; // DK Attacks: Unholy, Frost & Blood // damage spells Unit* pVictim = pTarget->getVictim(); Pet *pet = m_bot->GetPet(); float dist = m_bot->GetCombatDistance(pTarget, true); std::ostringstream out; switch (SpellSequence) { case SPELL_DK_UNHOLY: if (UNHOLY_PRESENCE > 0 && !m_bot->HasAura(UNHOLY_PRESENCE, EFFECT_INDEX_0) && !m_bot->HasAura(BLOOD_PRESENCE, EFFECT_INDEX_0) && !m_bot->HasAura(FROST_PRESENCE, EFFECT_INDEX_0) && m_ai->CastSpell(UNHOLY_PRESENCE, *m_bot)) return RETURN_CONTINUE; // check for BONE_SHIELD in combat if (BONE_SHIELD > 0 && !m_bot->HasAura(BONE_SHIELD, EFFECT_INDEX_0) && !m_bot->HasAura(ARMY_OF_THE_DEAD, EFFECT_INDEX_0) && m_ai->CastSpell(BONE_SHIELD, *m_bot)) return RETURN_CONTINUE; if (ARMY_OF_THE_DEAD > 0 && m_ai->GetAttackerCount() >= 5 && LastSpellUnholyDK < 1 && m_ai->CastSpell(ARMY_OF_THE_DEAD) && m_bot->HasAura(ARMY_OF_THE_DEAD, EFFECT_INDEX_0)) { out << " summoning Army of the Dead!"; m_ai->SetIgnoreUpdateTime(7); SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK + 1; return RETURN_CONTINUE; } if (PLAGUE_STRIKE > 0 && !pTarget->HasAura(PLAGUE_STRIKE, EFFECT_INDEX_0) && LastSpellUnholyDK < 2 && m_ai->CastSpell(PLAGUE_STRIKE, *pTarget)) { out << " Plague Strike"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK + 1; return RETURN_CONTINUE; } if (DEATH_GRIP > 0 && !pTarget->HasAura(DEATH_GRIP, EFFECT_INDEX_0) && LastSpellUnholyDK < 3 && m_ai->CastSpell(DEATH_GRIP, *pTarget)) { out << " Death Grip"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK + 1; return RETURN_CONTINUE; } if (DEATH_COIL > 0 && LastSpellUnholyDK < 4 && m_ai->CastSpell(DEATH_COIL, *pTarget)) { out << " Death Coil"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK + 1; return RETURN_CONTINUE; } if (DEATH_STRIKE > 0 && !pTarget->HasAura(DEATH_STRIKE, EFFECT_INDEX_0) && LastSpellUnholyDK < 5 && m_ai->CastSpell(DEATH_STRIKE, *pTarget)) { out << " Death Strike"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK + 1; return RETURN_CONTINUE; } if (UNHOLY_BLIGHT > 0 && !pTarget->HasAura(UNHOLY_BLIGHT, EFFECT_INDEX_0) && LastSpellUnholyDK < 6 && m_ai->CastSpell(UNHOLY_BLIGHT)) { out << " Unholy Blight"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK + 1; return RETURN_CONTINUE; } if (SCOURGE_STRIKE > 0 && LastSpellUnholyDK < 7 && m_ai->CastSpell(SCOURGE_STRIKE, *pTarget)) { out << " Scourge Strike"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK + 1; return RETURN_CONTINUE; } if (DEATH_AND_DECAY > 0 && m_ai->GetAttackerCount() >= 3 && dist <= ATTACK_DISTANCE && !pTarget->HasAura(DEATH_AND_DECAY, EFFECT_INDEX_0) && LastSpellUnholyDK < 8 && m_ai->CastSpell(DEATH_AND_DECAY)) { out << " Death and Decay"; m_ai->SetIgnoreUpdateTime(1); SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK + 1; return RETURN_CONTINUE; } if (SUMMON_GARGOYLE > 0 && !m_bot->HasAura(ARMY_OF_THE_DEAD, EFFECT_INDEX_0) && !pTarget->HasAura(SUMMON_GARGOYLE, EFFECT_INDEX_0) && LastSpellUnholyDK < 9 && m_ai->CastSpell(SUMMON_GARGOYLE, *pTarget)) { out << " summoning Gargoyle"; m_ai->SetIgnoreUpdateTime(2); SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK + 1; return RETURN_CONTINUE; } if (CORPSE_EXPLOSION > 0 && dist <= ATTACK_DISTANCE && LastSpellUnholyDK < 10 && m_ai->CastSpell(CORPSE_EXPLOSION, *pTarget)) { out << " Corpse Explosion"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK + 1; return RETURN_CONTINUE; } if (ANTI_MAGIC_SHELL > 0 && pTarget->IsNonMeleeSpellCasted(true) && !m_bot->HasAura(ANTI_MAGIC_SHELL, EFFECT_INDEX_0) && LastSpellUnholyDK < 11 && m_ai->CastSpell(ANTI_MAGIC_SHELL, *m_bot)) { out << " Anti-Magic Shell"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK + 1; return RETURN_CONTINUE; } if (ANTI_MAGIC_ZONE > 0 && pTarget->IsNonMeleeSpellCasted(true) && !m_bot->HasAura(ANTI_MAGIC_SHELL, EFFECT_INDEX_0) && LastSpellUnholyDK < 12 && m_ai->CastSpell(ANTI_MAGIC_ZONE, *m_bot)) { out << " Anti-Magic Zone"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK + 1; return RETURN_CONTINUE; } if (!pet && RAISE_DEAD > 0 && !m_bot->HasAura(ARMY_OF_THE_DEAD, EFFECT_INDEX_0) && LastSpellUnholyDK < 13 && m_ai->CastSpell(RAISE_DEAD)) { out << " summoning Ghoul"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK + 1; return RETURN_CONTINUE; } if (pet && GHOUL_FRENZY > 0 && pVictim == pet && !pet->HasAura(GHOUL_FRENZY, EFFECT_INDEX_0) && LastSpellUnholyDK < 14 && m_ai->CastSpell(GHOUL_FRENZY, *pet)) { out << " casting Ghoul Frenzy on pet"; SpellSequence = SPELL_DK_FROST; LastSpellUnholyDK = LastSpellUnholyDK + 1; return RETURN_CONTINUE; } if (LastSpellUnholyDK > 15) { LastSpellUnholyDK = 0; SpellSequence = SPELL_DK_FROST; return RETURN_NO_ACTION_OK; // Not really OK but that's just how the DK rotation works right now } LastSpellUnholyDK = 0; case SPELL_DK_FROST: if (FROST_PRESENCE > 0 && !m_bot->HasAura(FROST_PRESENCE, EFFECT_INDEX_0) && !m_bot->HasAura(BLOOD_PRESENCE, EFFECT_INDEX_0) && !m_bot->HasAura(UNHOLY_PRESENCE, EFFECT_INDEX_0) && m_ai->CastSpell (FROST_PRESENCE, *m_bot)) return RETURN_CONTINUE; if (DEATHCHILL > 0) { if (!m_bot->HasAura(DEATHCHILL, EFFECT_INDEX_0) && !m_bot->HasAura(KILLING_MACHINE, EFFECT_INDEX_0) && m_ai->CastSpell (DEATHCHILL, *m_bot)) return RETURN_CONTINUE; } else if (KILLING_MACHINE > 0) { if (!m_bot->HasAura(KILLING_MACHINE, EFFECT_INDEX_0) && !m_bot->HasAura(DEATHCHILL, EFFECT_INDEX_0) && m_ai->CastSpell (KILLING_MACHINE, *m_bot)) return RETURN_CONTINUE; } if (ICY_TOUCH > 0 && !pTarget->HasAura(ICY_TOUCH, EFFECT_INDEX_0) && LastSpellFrostDK < 1 && m_ai->CastSpell(ICY_TOUCH, *pTarget)) { out << " Icy Touch"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK + 1; return RETURN_CONTINUE; } if (OBLITERATE > 0 && LastSpellFrostDK < 2 && m_ai->CastSpell(OBLITERATE, *pTarget)) { out << " Obliterate"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK + 1; return RETURN_CONTINUE; } if (FROST_STRIKE > 0 && LastSpellFrostDK < 3 && m_ai->CastSpell(FROST_STRIKE, *pTarget)) { out << " Frost Strike"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK + 1; return RETURN_CONTINUE; } if (HOWLING_BLAST > 0 && m_ai->GetAttackerCount() >= 3 && LastSpellFrostDK < 4 && m_ai->CastSpell(HOWLING_BLAST, *pTarget)) { out << " Howling Blast"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK + 1; return RETURN_CONTINUE; } if (CHAINS_OF_ICE > 0 && !pTarget->HasAura(CHAINS_OF_ICE, EFFECT_INDEX_0) && LastSpellFrostDK < 5 && m_ai->CastSpell(CHAINS_OF_ICE, *pTarget)) { out << " Chains of Ice"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK + 1; return RETURN_CONTINUE; } if (RUNE_STRIKE > 0 && LastSpellFrostDK < 6 && m_ai->CastSpell(RUNE_STRIKE, *pTarget)) { out << " Rune Strike"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK + 1; return RETURN_CONTINUE; } if (ICY_CLUTCH > 0 && !pTarget->HasAura(ICY_CLUTCH, EFFECT_INDEX_0) && LastSpellFrostDK < 7 && m_ai->CastSpell(ICY_CLUTCH, *pTarget)) { out << " Icy Clutch"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK + 1; return RETURN_CONTINUE; } if (ICEBOUND_FORTITUDE > 0 && m_ai->GetHealthPercent() < 50 && pVictim == m_bot && !m_bot->HasAura(ICEBOUND_FORTITUDE, EFFECT_INDEX_0) && LastSpellFrostDK < 8 && m_ai->CastSpell(ICEBOUND_FORTITUDE, *m_bot)) { out << " Icebound Fortitude"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK + 1; return RETURN_CONTINUE; } if (MIND_FREEZE > 0 && pTarget->IsNonMeleeSpellCasted(true) && dist <= ATTACK_DISTANCE && LastSpellFrostDK < 9 && m_ai->CastSpell(MIND_FREEZE, *pTarget)) { out << " Mind Freeze"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK + 1; return RETURN_CONTINUE; } if (HUNGERING_COLD > 0 && m_ai->GetAttackerCount() >= 3 && dist <= ATTACK_DISTANCE && LastSpellFrostDK < 10 && m_ai->CastSpell(HUNGERING_COLD, *pTarget)) { out << " Hungering Cold"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK + 1; return RETURN_CONTINUE; } if (EMPOWER_WEAPON > 0 && LastSpellFrostDK < 11 && m_ai->CastSpell(EMPOWER_WEAPON, *m_bot)) { out << " Empower Rune Weapon"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK + 1; return RETURN_CONTINUE; } if (UNBREAKABLE_ARMOR > 0 && !m_bot->HasAura(UNBREAKABLE_ARMOR, EFFECT_INDEX_0) && m_ai->GetHealthPercent() < 70 && pVictim == m_bot && LastSpellFrostDK < 12 && m_ai->CastSpell(UNBREAKABLE_ARMOR, *m_bot)) { out << " Unbreakable Armor"; SpellSequence = SPELL_DK_BLOOD; LastSpellFrostDK = LastSpellFrostDK + 1; return RETURN_CONTINUE; } if (LastSpellFrostDK > 13) { LastSpellFrostDK = 0; SpellSequence = SPELL_DK_BLOOD; return RETURN_NO_ACTION_OK; // Not really OK, but that's just how the DK rotation works right now } LastSpellFrostDK = 0; case SPELL_DK_BLOOD: if (BLOOD_PRESENCE > 0 && !m_bot->HasAura(BLOOD_PRESENCE, EFFECT_INDEX_0) && !m_bot->HasAura(UNHOLY_PRESENCE, EFFECT_INDEX_0) && !m_bot->HasAura(FROST_PRESENCE, EFFECT_INDEX_0) && m_ai->CastSpell (BLOOD_PRESENCE, *m_bot)) return RETURN_CONTINUE; if (MARK_OF_BLOOD > 0 && !pTarget->HasAura(MARK_OF_BLOOD, EFFECT_INDEX_0) && LastSpellBloodDK < 1 && m_ai->CastSpell(MARK_OF_BLOOD, *pTarget)) { out << " Mark of Blood"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK + 1; return RETURN_CONTINUE; } if (BLOOD_STRIKE > 0 && LastSpellBloodDK < 2 && m_ai->CastSpell(BLOOD_STRIKE, *pTarget)) { out << " Blood Strike"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK + 1; return RETURN_CONTINUE; } if (PESTILENCE > 0 && m_ai->GetAttackerCount() >= 3 && LastSpellBloodDK < 3 && m_ai->CastSpell(PESTILENCE, *pTarget)) { out << " Pestilence"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK + 1; return RETURN_CONTINUE; } if (STRANGULATE > 0 && !pTarget->HasAura(STRANGULATE, EFFECT_INDEX_0) && LastSpellBloodDK < 4 && m_ai->CastSpell(STRANGULATE, *pTarget)) { out << " Strangulate"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK + 1; return RETURN_CONTINUE; } if (BLOOD_BOIL > 0 && m_ai->GetAttackerCount() >= 5 && dist <= ATTACK_DISTANCE && LastSpellBloodDK < 5 && m_ai->CastSpell(BLOOD_BOIL, *pTarget)) { out << " Blood Boil"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK + 1; return RETURN_CONTINUE; } if (HEART_STRIKE > 0 && LastSpellBloodDK < 6 && m_ai->CastSpell(HEART_STRIKE, *pTarget)) { out << " Heart Strike"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK + 1; return RETURN_CONTINUE; } if (VAMPIRIC_BLOOD > 0 && m_ai->GetHealthPercent() < 70 && !m_bot->HasAura(VAMPIRIC_BLOOD, EFFECT_INDEX_0) && LastSpellBloodDK < 7 && m_ai->CastSpell(VAMPIRIC_BLOOD, *m_bot)) { out << " Vampiric Blood"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK + 1; return RETURN_CONTINUE; } if (RUNE_TAP > 0 && m_ai->GetHealthPercent() < 70 && !m_bot->HasAura(VAMPIRIC_BLOOD, EFFECT_INDEX_0) && LastSpellBloodDK < 8 && m_ai->CastSpell(RUNE_TAP, *m_bot)) { out << " Rune Tap"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK + 1; return RETURN_CONTINUE; } if (HYSTERIA > 0 && m_ai->GetHealthPercent() > 25 && !m_bot->HasAura(HYSTERIA, EFFECT_INDEX_0) && LastSpellBloodDK < 9 && m_ai->CastSpell(HYSTERIA, *m_bot)) { out << " Hysteria"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK + 1; return RETURN_CONTINUE; } if (DANCING_WEAPON > 0 && !m_bot->HasAura(DANCING_WEAPON, EFFECT_INDEX_0) && LastSpellBloodDK < 10 && m_ai->CastSpell(DANCING_WEAPON, *pTarget)) { out << " summoning Dancing Rune Weapon"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK + 1; return RETURN_CONTINUE; } if (DARK_COMMAND > 0 && m_ai->GetHealthPercent() > 50 && pVictim != m_bot && !pTarget->HasAura(DARK_COMMAND, EFFECT_INDEX_0) && LastSpellBloodDK < 11 && m_ai->CastSpell(DARK_COMMAND, *pTarget)) { out << " Dark Command"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK + 1; return RETURN_CONTINUE; } if (pet && DEATH_PACT > 0 && m_ai->GetHealthPercent() < 50 && LastSpellBloodDK < 12 && m_ai->CastSpell(DEATH_PACT, *pet)) { out << " Death Pact (sacrifice pet)"; SpellSequence = SPELL_DK_UNHOLY; LastSpellBloodDK = LastSpellBloodDK + 1; return RETURN_CONTINUE; } if (LastSpellBloodDK > 13) { LastSpellBloodDK = 0; SpellSequence = SPELL_DK_UNHOLY; return RETURN_NO_ACTION_OK; // Not really OK but that's just how DK rotation works right now } } //if (m_ai->GetManager()->m_confDebugWhisper) // m_ai->TellMaster(out.str().c_str()); return RETURN_NO_ACTION_UNKNOWN; } // end DoNextCombatManeuver