bool PlayerbotClassAI::DoSupportRaid(Player *gPlayer, float radius, bool dResurrect, bool dGroupHeal, bool dHeal, bool dCure, bool dBuff) { bool needHeal = false; if (dGroupHeal || dHeal) { uint8 cntNeedHeal = 0; uint8 raidHPPercent = GetHealthPercentRaid(gPlayer, cntNeedHeal); if (dGroupHeal && raidHPPercent <=90 && cntNeedHeal > 1) { if (HealGroup(gPlayer, raidHPPercent, cntNeedHeal)) return true; } if (raidHPPercent < 60 ) needHeal = true; } //std::list<Unit*> unitList; //gPlayer->GetRaidMember(unitList,30); Group *pGroup = gPlayer->GetGroup(); if (!pGroup) return false; for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) { Unit* tPlayer = itr->getSource(); if(!tPlayer || gPlayer->IsHostileTo(tPlayer)) continue; if(GetPlayerBot()->GetAreaId() != tPlayer->GetAreaId()) continue; if(!m_bot->IsWithinDistInMap(tPlayer, radius)) { continue; } if(tPlayer->isDead()) // May be we can rez { if(!dResurrect) continue; if(needHeal) continue; //First heal others needing heal if(tPlayer->GetGUID() == GetPlayerBot()->GetGUID()) continue; if(tPlayer->IsNonMeleeSpellCasted(true)) continue; //Already rez if(RezTarget(tPlayer)) { return true; } else continue; } if (dHeal) { uint8 tarHPPercent = tPlayer->GetHealth()*100 / tPlayer->GetMaxHealth(); if (tarHPPercent < 100 && HealTarget(tPlayer, tarHPPercent)) return true; } if (needHeal && dHeal) continue; //First heal others needing heal if (dCure && CureTarget(tPlayer)) return true; if (dBuff && BuffPlayer(tPlayer)) return true; } return false; }
void PlayerbotShamanAI::DoNextCombatManeuver(Unit *pTarget) { if (!pTarget || pTarget->isDead()) return; PlayerbotAI *ai = GetAI(); if (!ai) return; Player *m_bot = GetPlayerBot(); if (!m_bot || m_bot->isDead()) return; Unit *pVictim = pTarget->getVictim(); Unit *m_tank = FindMainTankInRaid(GetMaster()); if (!m_tank && m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup()) { FindMainTankInRaid(m_bot); } if (!m_tank) { m_tank = m_bot; } uint32 masterHP = GetMaster()->GetHealth()*100 / GetMaster()->GetMaxHealth(); float pDist = m_bot->GetDistance(pTarget); uint8 pThreat = GetThreatPercent(pTarget); uint8 reqHeal = 0; uint8 OwnPartyHP = GetHealthPercentRaid(m_bot, reqHeal); switch(ai->GetScenarioType()) { case SCENARIO_DUEL: ((ai->GetHealthPercent() < 80 && CastSpell(LESSER_HEAL)) || CastSpell(LIGHTNING_BOLT, pTarget)); return; } // Cast CC breakers if any match found (include any dispels first) does not work yet //uint32 ccSpells[4] = { R_ESCAPE_ARTIST, R_EVERY_MAN_FOR_HIMSELF, R_WILL_OF_FORSAKEN, R_STONEFORM }; //if (ai->GetManaPercent() < 35) { ccSpells[0] = 0; ccSpells[1] = 0; } //We dont have any mana to waste... //if (castSelfCCBreakers(ccSpells)) { } // Most of them don't trigger gcd #pragma region Choose Actions // Choose actions accoring to talents if (m_tank->GetGUID() == m_bot->GetGUID()) { m_role=BOT_ROLE_TANK; } // Hey! I am Main Tank else if (TALENT_ENHANCEMENT) { m_role = BOT_ROLE_DPS_MELEE; } else if (TALENT_ELEMENTAL) { m_role = BOT_ROLE_DPS_RANGED; } else if (TALENT_RESTO) { m_role = BOT_ROLE_SUPPORT; } else { m_role = BOT_ROLE_DPS_MELEE; } //Unknown build or low level.. Mainly attack // if i am under attack and if i am not tank or offtank: change target if needed if (m_tank->GetGUID() != m_bot->GetGUID() && isUnderAttack() ) { if (pVictim && pVictim->GetGUID() == m_bot->GetGUID() && pDist <= 2) { } // My target is almost up to me, no need to search else //Have to select nearest target { Unit *curAtt = GetNearestAttackerOf(m_bot); if (curAtt && curAtt->GetGUID() != pTarget->GetGUID()) { m_bot->SetSelection(curAtt->GetGUID()); //ai->AddLootGUID(curAtt->GetGUID()); DoNextCombatManeuver(curAtt); //Restart new update to get variables fixed.. return; } } //my target is attacking me } #pragma endregion // Choose Weapon Enchant if (ChangeWeaponEnchants()) return; if (TALENT_ELEMENTAL){ if (!m_bot->HasAura(WATER_SHIELD) && CastSpell(WATER_SHIELD,m_bot)) { return; }} if (TALENT_ENHANCEMENT){ if (!m_bot->HasAura(LIGHTNING_SHIELD) && CastSpell(LIGHTNING_SHIELD,m_bot)) { return; }} if (TALENT_RESTO){ if (!m_bot->HasAura(WATER_SHIELD) && CastSpell(WATER_SHIELD,m_bot)) { return; }} // Choose shield /* if (EARTH_SHIELD && ai->GetHealthPercent() < 80 && isUnderAttack()) { if (CastSpell(EARTH_SHIELD,m_bot)) { return; } } else if (WATER_SHIELD && ai->GetManaPercent() < 40) { if (CastSpell(WATER_SHIELD,m_bot)) { return; } } else if (LIGHTNING_SHIELD && ( isUnderAttack() || m_tank->GetGUID() == m_bot->GetGUID() ) && !(m_bot->HasAura(WATER_SHIELD) && ai->GetManaPercent() < 80) ) { if (CastSpell(LIGHTNING_SHIELD,m_bot)) { return; } } else if (CastSpell(WATER_SHIELD,m_bot)) { return; } */ // If there's a cast stop if(m_bot->HasUnitState(UNIT_STAT_CASTING)) return; switch(m_role) { #pragma region BOT_ROLE_TANK / BOT_ROLE_OFFTANK case BOT_ROLE_TANK: case BOT_ROLE_OFFTANK: if (!TALENT_ELEMENTAL && !TALENT_RESTO) { TakePosition(pTarget); } else { TakePosition(pTarget,BOT_ROLE_DPS_RANGED); } // mob will come to you sooner or later no need to hurry // Do support stuff if (!m_bot->isMoving() && ChangeTotems(m_role)) { return; } if (ai->GetManaPercent() > 70 && DoSupportRaid(m_bot)) { return; } break; #pragma endregion #pragma region BOT_ROLE_DPS_MELEE case BOT_ROLE_DPS_MELEE: TakePosition(pTarget); // Do support stuff if (!m_bot->isMoving() && ChangeTotems(m_role)) { return; } if (ai->GetManaPercent() > 40 && DoSupportRaid(m_bot)) { return; } break; #pragma endregion #pragma region BOT_ROLE_DPS_RANGED case BOT_ROLE_DPS_RANGED: TakePosition(pTarget); // Do support stuff if (!m_bot->isMoving() && ChangeTotems(m_role)) { return; } if (ai->GetManaPercent() > 40 && DoSupportRaid(m_bot)) { return; } break; #pragma endregion #pragma region BOT_ROLE_SUPPORT case BOT_ROLE_SUPPORT: TakePosition(pTarget); // Do support stuff if (!m_bot->isMoving() && ChangeTotems(m_role)) { return; } if (DoSupportRaid(m_bot)) { return; } //heal pets and bots Unit *target = DoSelectLowestHpFriendly(40, 1000); if(target && target->isAlive() && HealTarget(target, target->GetHealth()*100 / target->GetMaxHealth()) ) { return; } break; #pragma endregion } #pragma region ShamanCommon //Defensive Stuff if (m_tank->GetGUID() != m_bot->GetGUID() && pVictim && pVictim->GetGUID() == m_bot->GetGUID() ) { if (pDist > 5 && CastSpell(FROST_SHOCK, pTarget)) { return; } if ((pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_BEAST || pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_HUMANOID) && CastSpell(HEX, pTarget)) { return; } // no gcd if (CastSpell(WIND_SHEAR, pTarget)) { } // no gcd } if (m_bot->getRace() == (uint8) RACE_BLOODELF && pDist < 8 && pTarget->IsNonMeleeSpellCasted(true) && CastSpell(R_ARCANE_TORRENT, pTarget)) { } //no gcd if (pTarget->IsNonMeleeSpellCasted(true) && CastSpell(WIND_SHEAR, pTarget)) { } //no gcd if (m_bot->getRace() == (uint8) RACE_TAUREN && pVictim && pVictim->GetGUID() == m_bot->GetGUID() && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return; } //Catch if (pTarget->HasUnitMovementFlag(UNIT_FLAG_FLEEING)) { if (CastSpell(FROST_SHOCK,pTarget)) return; } //Buff and restores if ( ( (ai->GetHealthPercent() < 60 && isUnderAttack()) || (ai->GetManaPercent() < 30) ) && CastSpell(SHAMANISTIC_RAGE, m_bot)) { return; } if (m_bot->getRace() == (uint8) RACE_TROLL && CastSpell(R_BERSERKING,m_bot)) {} // no GCD if (m_bot->getRace() == (uint8) RACE_ORC && CastSpell(R_BLOOD_FURY,m_bot)) {} // no GCD if (!m_bot->HasAura(HEROISM) && !m_bot->HasAura(EXHAUSTION) && !m_bot->HasAura(SATED) && CastSpell(HEROISM,m_bot)) { return; } if (m_role != BOT_ROLE_SUPPORT && CastSpell(NATURES_SWIFTNESS, m_bot)) { } //healers keep it for healing no gcd else if (CastSpell(ELEMENTAL_MASTERY, m_bot)) { } //no gcd // If at threat limit, use WIND_SHEAR to reduce threat if (pThreat > threatThreshold && m_tank->GetGUID() != m_bot->GetGUID() && !isUnderAttack()) { if (m_tank->getVictim() && m_tank->getVictim()->GetGUID() != pTarget->GetGUID()) // I am attacking wrong target!! { m_bot->SetSelection(m_tank->getVictim()->GetGUID()); return; } else { if (CastSpell(WIND_SHEAR,pTarget)) { return; } //Lets see if we can manage else { return; } //use no spells and wait threat to be reduced } } if (TALENT_ELEMENTAL) { if (CastSpell(ELEMENTAL_MASTERY, m_bot)) { } //no gcd if (!pTarget->HasAura(FLAME_SHOCK,m_bot->GetGUID()) && CastSpell(FLAME_SHOCK,pTarget)) { return; } if (CastSpell(LAVA_BURST,pTarget)) { return; } if (CastSpell(CHAIN_LIGHTNING,pTarget)) { return; } if (CastSpell(LIGHTNING_BOLT,pTarget)) { return; } } //dps if (MAELSTROM_WEAPON) { Aura *maelaura = m_bot->GetAura(MAELSTROM_WEAPON); if (maelaura && maelaura->GetStackAmount() == 5) { if ((isUnderAttack(m_tank,3) || m_tank->GetGUID() == m_bot->GetGUID()) && CastSpell(CHAIN_LIGHTNING,pTarget,true,true)) { return; } if (CastSpell(LIGHTNING_BOLT,pTarget,true,true)) { return; } } } if (CastSpell(FLAME_SHOCK,pTarget)) { return; } if (CastSpell(STORMSTRIKE,pTarget,true,true)) { return; } //if (!TALENT_ENHANCEMENT && CanCast(LAVA_BURST,pTarget,true) && pTarget->HasAura(FLAME_SHOCK,m_bot->GetGUID()) && CastSpell(LAVA_BURST,pTarget,false)) { return; } if (CastSpell(FERAL_SPIRIT,m_bot)) { return; } if (CanCast(EARTH_SHOCK,pTarget,true) && (pTarget->HasAura(STORMSTRIKE,m_bot->GetGUID()) || pTarget->HasAura(FLAME_SHOCK,m_bot->GetGUID()) ) && CastSpell(EARTH_SHOCK,pTarget)) { return; } //if (CanCast(FLAME_SHOCK,pTarget) && CastSpell(FLAME_SHOCK,pTarget)) { return; } if (CastSpell(LAVA_LASH,pTarget,true,true)) { return; } if (CastSpell(FIRE_NOVA,pTarget)) { return; } //if ((isUnderAttack(m_tank,4) || m_tank->GetGUID() == m_bot->GetGUID()) && CastSpell(FIRE_NOVA,pTarget)) { return; } if (ai->GetManaPercent() > 60 && castDispel(PURGE,pTarget)) { return; } //PURGE but dont overpurge #pragma endregion // drink potion if support / healer (Other builds simply overuse mana and waste mana pots) if(ai->GetManaPercent() < 5 && (m_role == BOT_ROLE_SUPPORT || m_role == BOT_ROLE_HEALER) ) { Item *pItem = ai->FindPotion(); if(pItem != NULL) { if (pItem->GetSpell() && m_bot->HasSpellCooldown(pItem->GetSpell()) ) { return; } //pot is in cooldown ai->UseItem(*pItem); } } } //end DoNextCombatManeuver
void PlayerbotDruidAI::DoNextCombatManeuver(Unit *pTarget) { if (!pTarget || pTarget->isDead()) return; PlayerbotAI *ai = GetAI(); if (!ai) return; Player *m_bot = GetPlayerBot(); if (!m_bot || m_bot->isDead()) return; Unit *pVictim = pTarget->getVictim(); Unit *m_tank = FindMainTankInRaid(GetMaster()); if (!m_tank && m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup()) { FindMainTankInRaid(m_bot); } if (!m_tank) { m_tank = m_bot; } uint32 masterHP = GetMaster()->GetHealth()*100 / GetMaster()->GetMaxHealth(); float pDist = m_bot->GetDistance(pTarget); uint8 pThreat = GetThreatPercent(pTarget); uint8 reqHeal = 0; uint8 OwnPartyHP = GetHealthPercentRaid(m_bot, reqHeal); #pragma region Select behaviour if (m_tank->GetGUID() == m_bot->GetGUID()) // Hey! I am Main Tank { if (TALENT_FERAL && BEAR_FORM) { m_role = BOT_ROLE_TANK; } //Just Keep Tanking dont even change forms for healing else { if (TALENT_BALANCE) { if ((ai->GetHealthPercent() <= 40 || masterHP <30 ) && (ai->GetManaPercent() >= 40)) { m_role = BOT_ROLE_SUPPORT; } else if (OwnPartyHP < 20 && ai->GetManaPercent() >= 30) { m_role = BOT_ROLE_SUPPORT; } else if (ai->GetManaPercent() < 25 ) { m_role = BOT_ROLE_TANK; } else { m_role = BOT_ROLE_DPS_RANGED; } } else //I am both healer and tank?? Hmm { if ((ai->GetHealthPercent() <= 70 || masterHP <70 ) && (ai->GetManaPercent() >= 50)) { m_role = BOT_ROLE_SUPPORT; } else if (OwnPartyHP < 20 && ai->GetManaPercent() >= 30) { m_role = BOT_ROLE_SUPPORT; } else if (ai->GetManaPercent() < 15 ) { m_role = BOT_ROLE_TANK; } else { m_role = BOT_ROLE_DPS_RANGED; } } } } else if (isUnderAttack() && !( ai->GetForm() == FORM_MOONKIN || ai->GetForm() == FORM_TREE) ) // if i am under attack { // Keep being in Cat Form if you can reduce threat if (ai->GetForm() == FORM_CAT && CastSpell(COWER,pTarget)) {return; } else if (TALENT_RESTO && ai->GetManaPercent() > 10 ) { m_role = BOT_ROLE_SUPPORT; } else { m_role = BOT_ROLE_OFFTANK; } } else if (TALENT_FERAL && CAT_FORM) { // If has any feral forms at all if ((ai->GetHealthPercent() <= 40 || masterHP <40 ) && (ai->GetManaPercent() >= 40)) { m_role = BOT_ROLE_SUPPORT; } else if (OwnPartyHP < 30 && ai->GetManaPercent() >= 30) { m_role = BOT_ROLE_SUPPORT; } else{ m_role = BOT_ROLE_DPS_MELEE; } } else if (TALENT_BALANCE) { if ((ai->GetHealthPercent() <= 50 || masterHP <40 ) && (ai->GetManaPercent() >= 10)) { m_role = BOT_ROLE_SUPPORT; } else if (OwnPartyHP < 40 && ai->GetManaPercent() >= 30) { m_role = BOT_ROLE_SUPPORT; } else { m_role = BOT_ROLE_DPS_RANGED; } } else if (TALENT_RESTO) { m_role = BOT_ROLE_SUPPORT; } else { // Unknown build or low level : Do not change forms rapidly.. if ( (ai->GetManaPercent() < 30 && BEAR_FORM) || ( (ai->GetForm() == FORM_CAT || ai->GetForm() == FORM_DIREBEAR || ai->GetForm() == FORM_BEAR) && ai->GetManaPercent() < 70 ) ) m_role = BOT_ROLE_DPS_MELEE; else { m_role = BOT_ROLE_DPS_RANGED; } } if (!isUnderAttack() && m_tank->GetGUID() != m_bot->GetGUID()) { // Select Attacking target if (pVictim && pVictim->GetGUID() == m_bot->GetGUID() && pDist <= 2) {} //if my target is attacking me continue else { Unit *curAtt = GetNearestAttackerOf(m_bot); if (curAtt && curAtt->GetGUID() != pTarget->GetGUID()) { m_bot->SetSelection(curAtt->GetGUID()); //ai->AddLootGUID(curAtt->GetGUID()); DoNextCombatManeuver(curAtt); //Restart new update to get variables fixed.. return; } } //my target is attacking me } #pragma endregion // If there's a cast stop if (m_bot->HasUnitState(UNIT_STAT_CASTING)) return; // Return to normal form from non combat forms if (ai->GetForm() == FORM_NONE || ai->GetForm() == FORM_CAT || ai->GetForm() == FORM_TREE || ai->GetForm() == FORM_MOONKIN || ai->GetForm() == FORM_DIREBEAR || ai->GetForm() == FORM_BEAR ) { } //Those are valid incombat auras else if (ai->GetForm() != FORM_NONE && ChangeForm(1)) { } //return to caster form switch(m_role) { #pragma region BOT_ROLE_DPS_MELEE case BOT_ROLE_DPS_MELEE: //ai->TellMaster("DruidCombat"); // Do caster form stuff if (ai->GetForm() == FORM_NONE) { //We have little mana probably cant change form if (ai->GetManaPercent() < 20 && CastSpell (INNERVATE, m_bot) ) { return; } else if(m_bot->getRace() == (uint8) RACE_TAUREN && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return;} else if(DoSupportRaid(GetMaster(),false,false,false)) return; else if(m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup() && DoSupportRaid(m_bot,false,false,false)) { return; } } if (CAT_FORM) { if (ChangeForm(CAT_FORM)) { return; } } else if (BEAR_FORM) { if (ChangeForm(BEAR_FORM)) { return; } } else if (ai->GetForm() != FORM_NONE && ChangeForm(1)) { } //Normal Form TakePosition(pTarget); break; #pragma endregion #pragma region BOT_ROLE_TANK / BOT_ROLE_OFFTANK case BOT_ROLE_OFFTANK: case BOT_ROLE_TANK: // It is a tank druid or a defending druid // Do what you must before getting attacked... if (ai->GetForm() == FORM_NONE) { // Non tank stuff to avoid if (m_tank->GetGUID() != m_bot->GetGUID()) { if (ROOTS && !pTarget->HasAura(CYCLONE) && !pTarget->HasAura(HIBERNATE) && CastSpell(ROOTS, pTarget)) { return; } if (CYCLONE && pDist > 5 && !pTarget->HasAura(ROOTS) && !pTarget->HasAura(HIBERNATE) && CastSpell(CYCLONE, pTarget)) { return; } if (HIBERNATE && pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_BEAST && !pTarget->HasAura(ROOTS) && !pTarget->HasAura(CYCLONE) && CastSpell(HIBERNATE, pTarget)) { return; } //if (m_bot->getRace() == (uint8) RACE_NIGHTELF && isUnderAttack() && CastSpell(R_SHADOWMELD, m_bot)) { return; } } // Things to do wheter Tank or not if (m_bot->getRace() == (uint8) RACE_TAUREN && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return; } //no gcd if (ai->GetManaPercent() < 20 && CastSpell (INNERVATE, m_bot) ) { return; } //We have little mana probably cant change form } TakePosition(pTarget); if (ChangeForm(BEAR_FORM)) { return; } // if i am main tank, protect master by taunt if(m_tank->GetGUID() == m_bot->GetGUID()) { // Taunt if needed (Only for master) Unit *curAtt = GetAttackerOf(GetMaster()); if (curAtt) { if (isUnderAttack(GetMaster(),2) && CastSpell(CHALLENGING_ROAR, curAtt)) { return; } if (CastSpell(GROWL, curAtt)) { return; } } // My target is not attacking me, taunt.. if (pVictim && pVictim->GetGUID() != m_bot->GetGUID() && CastSpell(GROWL, pTarget) ) { return; } } break; #pragma endregion #pragma region BOT_ROLE_DPS_RANGED case BOT_ROLE_DPS_RANGED: if ( ai->GetManaPercent() < 20 && CastSpell (INNERVATE, m_bot)) { return; } // Do caster form stuff if (ai->GetForm() == FORM_NONE) { if(DoSupportRaid(GetMaster())) return; else if(m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup() && DoSupportRaid(m_bot)) { return; } } if (MOONKIN_FORM) { if (ChangeForm(MOONKIN_FORM)) { return; } } else if (ai->GetForm() != FORM_NONE && ChangeForm(1)) { } //Normal Form TakePosition(pTarget); // BUFF UP if(DoSupportRaid(GetMaster(),false,false,false)) return; else if(m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup() && DoSupportRaid(m_bot,false,false,false)) { return; } break; #pragma endregion #pragma region BOT_ROLE_SUPPORT case BOT_ROLE_SUPPORT: if ( ai->GetManaPercent() < 20 && CastSpell (INNERVATE,m_bot)) { return; } //Get to tree form only if you will no longer cast attack spells if( TREE_OF_LIFE_FORM && (ai->GetManaPercent() < offensiveSpellThreshold || isUnderAttack()) ) { if (ChangeForm(TREE_OF_LIFE_FORM)) { return; } } else if (ai->GetForm() != FORM_NONE && ChangeForm(1)) { } //Normal Form no gcd TakePosition(pTarget); //RezGroup(REBIRTH, GetMaster()); if (DoSupportRaid(GetMaster())) { return; } if (m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup() && DoSupportRaid(m_bot)) { return; } //heal pets and bots Unit *target = DoSelectLowestHpFriendly(30, 1000); if(target && target->isAlive() && HealTarget(target, target->GetHealth()*100 / target->GetMaxHealth()) ) { return; } break; #pragma endregion } #pragma region DruidCommon // Common Dps and protection routine if (ai->GetHealthPercent() <= 70 && CastSpell(BARKSKIN,m_bot)) { return; } if (isUnderAttack() && CastSpell(NATURES_GRASP,m_bot)) { return; } if (ai->GetForm() == FORM_CAT) { // If at threat limit, use Cower to reduce threat if (pThreat > threatThreshold && m_tank->GetGUID() != m_bot->GetGUID() && !isUnderAttack()) { if (m_tank->getVictim() && m_tank->getVictim()->GetGUID() != pTarget->GetGUID()) // I am attacking wrong target!! { m_bot->SetSelection(m_tank->getVictim()->GetGUID()); return; } else { if (CastSpell(COWER,pTarget)) { return; } //Lets see if we can manage else { return; } //use no spells and wait threat to be reduced } } if (CastSpell(FERAL_CHARGE_CAT,pTarget)) { return; } if (m_bot->GetComboPoints() >= 1 && pTarget->IsNonMeleeSpellCasted(true) && CastSpell(MAIM, pTarget)) { return; } if (CastSpell(BERSERK, m_bot)) { return; } if (ai->GetHealthPercent() <= 75 && CastSpell(SURVIVAL_INSTINCTS, m_bot)) { return; } if (isUnderAttack() && CastSpell(NATURES_GRASP, m_bot)) { return; } if (CastSpell(FAERIE_FIRE_FERAL, pTarget)) { return; } if (m_bot->GetComboPoints() < 5) { if (CastSpell(RAKE, pTarget)) { return; } if (CastSpell(MANGLE_CAT, pTarget)) { return; } if (!pTarget->HasInArc(M_PI,m_bot) && CastSpell(SHRED, pTarget)) { return; } if (ai->GetEnergyAmount() > 65 && CastSpell(MANGLE_CAT, pTarget)) { return; } //Spam mangle if cannot cast shred if (ai->GetEnergyAmount() > 65 && CastSpell(CLAW, pTarget) ) { return; } //Spam Claw if there is no mangle // if (CanCast(COWER, pTarget) && CastSpell(COWER, pTarget)) { return; } //if still nothing, use COWER to reduce threat } else { if (CastSpell(SAVAGE_ROAR)) { return; } if (CastSpell(RIP, pTarget)) { return; } if (ai->GetEnergyAmount() >= 65 && CastSpell(FEROCIOUS_BITE, pTarget)) { return; } //maxhit for feracious bite } if (CastSpell(TIGERS_FURY, m_bot)) { return; } //if nothing is ready yet, use tigers fury } else if (ai->GetForm() == FORM_DIREBEAR || ai->GetForm() == FORM_BEAR) { // If at threat limit, stop if (pThreat > threatThreshold && m_tank->GetGUID() != m_bot->GetGUID() && !isUnderAttack() ) { //Change to tank's target if (m_tank->getVictim() && m_tank->getVictim()->GetGUID() != pTarget->GetGUID()) { m_bot->SetSelection(m_tank->getVictim()->GetGUID()); } return; //use no spells and wait threat to be reduced } if (CastSpell(FERAL_CHARGE_BEAR,pTarget)) { return; } if (CastSpell(BASH, pTarget,true,true)) { return; } //Need check for immunity if (CastSpell(BERSERK, m_bot)) { return; } if (CastSpell(DEMORALIZING_ROAR, pTarget)) { return; } if (ai->GetHealthPercent() > 90 && ai->GetRageAmount() < 50 && CastSpell(ENRAGE, m_bot)) { return; } if (ai->GetHealthPercent() <= 75 && CastSpell(SURVIVAL_INSTINCTS, m_bot)) { return; } if ( ( ai->GetHealthPercent() <= 30 || (ai->GetHealthPercent() < 85 && m_tank->GetGUID() != m_bot->GetGUID()) ) && CastSpell(FRENZIED_REGENERATION)) { return; } if (CastSpell(FAERIE_FIRE_FERAL, pTarget)) { return; } if (CastSpell(MANGLE_BEAR, pTarget)) { return; } if ((ai->GetRageAmount() > 70 || m_tank->GetGUID() == m_bot->GetGUID()) && CastSpell(SWIPE_BEAR, pTarget)) { return; } if (ai->GetRageAmount() > 50 && CastSpell(MAUL, pTarget)) {} // Low Priority, Next Attack effect if (ai->GetRageAmount() > 60 && CastSpell(LACERATE, pTarget)) { return; } //Currently applies only 1 } else { //Defensive stuff if (m_tank->GetGUID() != m_bot->GetGUID() && pVictim && pVictim->GetGUID() == m_bot->GetGUID() ) { if (ROOTS && !pTarget->HasAura(CYCLONE) && !pTarget->HasAura(HIBERNATE) && CastSpell(ROOTS, pTarget)) { return; } if (CYCLONE && pDist > 5 && !pTarget->HasAura(ROOTS) && !pTarget->HasAura(HIBERNATE) && CastSpell(CYCLONE, pTarget)) { return; } if (HIBERNATE && pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_BEAST && !pTarget->HasAura(ROOTS) && !pTarget->HasAura(CYCLONE) && CastSpell(HIBERNATE, pTarget)) { return; } //if (m_bot->getRace() == (uint8) RACE_NIGHTELF && isUnderAttack() && CastSpell(R_SHADOWMELD, m_bot)) { return; } if (m_bot->getRace() == (uint8) RACE_TAUREN && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return; } } if (CastSpell(FAERIE_FIRE, pTarget)) { return; } // If at threat limit, stop if (pThreat > threatThreshold && m_tank->GetGUID() != m_bot->GetGUID() && !isUnderAttack() ) { //Change to tank's target if (m_tank->getVictim() && m_tank->getVictim()->GetGUID() != pTarget->GetGUID()) { m_bot->SetSelection(m_tank->getVictim()->GetGUID()); } return; //use no spells and wait threat to be reduced } // Continue attacking if theres excess mana (for healers) if (m_role == BOT_ROLE_SUPPORT && ai->GetManaPercent() < offensiveSpellThreshold) { return; } if (m_role != BOT_ROLE_SUPPORT && CastSpell(NATURES_SWIFTNESS, m_bot)) { } //only balance no gcd if (m_bot->HasAura(NATURES_SWIFTNESS) && CastSpell(STARFIRE, pTarget)) { return; } if (CastSpell(INSECT_SWARM, pTarget)) { return; } if (CastSpell(TYPHOON, pTarget)) { return; } if (isUnderAttack(m_tank,4) && CastSpell(HURRICANE, pTarget)) { ai->SetIgnoreUpdateTime(8); return; } if (isUnderAttack(m_tank,5) && CastSpell(FORCE_OF_NATURE, m_bot)) { return; } if (isUnderAttack(m_tank,4) && CastSpell(STARFALL, pTarget)) { return; } if (CastSpell(MOONFIRE, pTarget)) { return; } if (CastSpell(WRATH, pTarget)) { return; } if (CastSpell(STARFIRE, pTarget)) { return; } } // If there is nothing else to do buff UP if (m_role == BOT_ROLE_DPS_MELEE) //Those already healed and buffed or should never buff in combat { if (DoSupportRaid(GetMaster(),false,false,false)) { return; } if (m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup() && DoSupportRaid(m_bot,false,false,false)) { return; } } // drink potion if support / healer (Other builds simply overuse mana and waste mana pots) if(ai->GetManaPercent() < 5 && (m_role == BOT_ROLE_SUPPORT || m_role == BOT_ROLE_HEALER) ) { Item *pItem = ai->FindPotion(); if(pItem != NULL) { if (pItem->GetSpell() && m_bot->HasSpellCooldown(pItem->GetSpell()) ) { return; } //pot is in cooldown ai->UseItem(*pItem); } } #pragma endregion } //end DoNextCombatManeuver
void PlayerbotPaladinAI::DoNextCombatManeuver(Unit *pTarget) { if (!pTarget || pTarget->isDead()) return; PlayerbotAI *ai = GetAI(); if (!ai) return; Player *m_bot = GetPlayerBot(); if (!m_bot || m_bot->isDead()) return; Unit *pVictim = pTarget->getVictim(); Unit *m_tank = FindMainTankInRaid(GetMaster()); if (!m_tank && m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup()) { FindMainTankInRaid(m_bot); } if (!m_tank) { m_tank = m_bot; } uint32 masterHP = GetMaster()->GetHealth()*100 / GetMaster()->GetMaxHealth(); float pDist = m_bot->GetDistance(pTarget); uint8 pThreat = GetThreatPercent(pTarget); uint8 reqHeal = 0; uint8 OwnPartyHP = GetHealthPercentRaid(m_bot, reqHeal); // Fill mana if needed if (m_bot->getRace() == (uint8) RACE_BLOODELF && pDist < 8 && ai->GetManaPercent() < 20 && CastSpell(R_ARCANE_TORRENT, pTarget)) { } //no gcd if (ai->GetManaPercent() < 30 && CastSpell (DIVINE_PLEA, m_bot)) { return; } // If hp is too low divine shield if (ai->GetHealthPercent() < 20 && (!m_bot->HasAura(DIVINE_SHIELD) || !m_bot->HasAura(HOP) || !m_bot->HasAura(SACRED_SHIELD))) { if (!m_bot->HasAura(FORBEARANCE)) { if (CastSpell(DIVINE_SHIELD,m_bot)) { return; } if (CastSpell(HOP,m_bot)) { return; } } else if (CastSpell(SACRED_SHIELD,m_bot)) { return; } } // if i am under attack and if i am not tank or offtank: change target if needed if (m_tank->GetGUID() != m_bot->GetGUID() && !TALENT_PROT && isUnderAttack() ) { // Keep hitting but reduce threat if (CastSpell(HOS,m_bot,true,true)) { } //else if (m_bot->getRace() == (uint8) RACE_NIGHTELF && CastSpell(R_SHADOWMELD,m_bot)) { return; } else //I cannot reduce threat so { if (pVictim && pVictim->GetGUID() == m_bot->GetGUID() && pDist <= 2) { } // My target is almost up to me, no need to search else //Have to select nearest target { Unit *curAtt = GetNearestAttackerOf(m_bot); if (curAtt && curAtt->GetGUID() != pTarget->GetGUID()) { m_bot->SetSelection(curAtt->GetGUID()); //ai->AddLootGUID(curAtt->GetGUID()); DoNextCombatManeuver(curAtt); //Restart new update to get variables fixed.. return; } } //my target is attacking me } } #pragma region Choose Actions // Choose actions accoring to talents if (m_tank->GetGUID() == m_bot->GetGUID()) // Hey! I am Main Tank { if (TALENT_PROT) { m_role=BOT_ROLE_TANK; } //Just Keep Tanking else { if (TALENT_RETRI) { if ((ai->GetHealthPercent() <= 40 || masterHP <40 ) && (ai->GetManaPercent() >= 40)) { m_role = BOT_ROLE_SUPPORT; } else if (OwnPartyHP < 40 && ai->GetManaPercent() >= 30) { m_role = BOT_ROLE_SUPPORT; } else { m_role = BOT_ROLE_TANK; } //have no shield but can tank if you think so } else if (TALENT_HOLY) //I am both healer and tank?? Hmm { if ((ai->GetHealthPercent() <= 70 || masterHP <70 ) && (ai->GetManaPercent() >= 50))m_role = BOT_ROLE_SUPPORT; else if (OwnPartyHP < 20 && ai->GetManaPercent() >= 30) { m_role = BOT_ROLE_SUPPORT; } else m_role = BOT_ROLE_TANK; } else { m_role = BOT_ROLE_TANK; } //Unknown build or low level } } else if (TALENT_RETRI) { if ((ai->GetHealthPercent() <= 40 || masterHP <40 ) && (ai->GetManaPercent() >= 40)) { m_role = BOT_ROLE_SUPPORT; } else if (OwnPartyHP < 40 && ai->GetManaPercent() >= 30) {m_role = BOT_ROLE_SUPPORT;} else { m_role = BOT_ROLE_DPS_MELEE; } } else if (TALENT_PROT) { if ((ai->GetHealthPercent() <= 30 || masterHP <40 ) && (ai->GetManaPercent() >= 20)) { m_role = BOT_ROLE_SUPPORT; } else if (OwnPartyHP < 40 && ai->GetManaPercent() >= 40) { m_role = BOT_ROLE_SUPPORT; } else { m_role = BOT_ROLE_OFFTANK; } } else if (TALENT_HOLY) { m_role = BOT_ROLE_SUPPORT; } else { m_role = BOT_ROLE_DPS_MELEE; } //Unknown build or low level.. Mainly attack //takepos if (m_role == BOT_ROLE_SUPPORT || m_role == BOT_ROLE_HEALER) TakePosition(pTarget,BOT_ROLE_DPS_MELEE,0.5f); else TakePosition(pTarget,m_role); // If there's a cast stop if(m_bot->HasUnitState(UNIT_STATE_CASTING)) return; Unit *target = DoSelectLowestHpFriendly(40, 1000); switch(m_role) { #pragma region BOT_ROLE_SUPPORT case BOT_ROLE_SUPPORT: ChangeAura(CONCENTRATION_AURA); if (!TALENT_PROT && m_tank->GetGUID() != m_bot->GetGUID()) m_bot->RemoveAurasDueToSpell(RIGHTEOUS_FURY); // Choose Seal if (SOW && ai->GetManaPercent() <= 30) { if (CastSpell(SOW,m_bot)) { return; } } else if (m_bot->HasAura(SOW) && ai->GetManaPercent() < 85) { } // Paladin was striving for mana, keep until he got most of his mana back else if(SOL && ai->GetHealthPercent() < 40) { if(CastSpell(SOL,m_bot)) { return; } } else if(CastSpell(SOR, m_bot)) { return; } if (!m_bot->HasAura(FORBEARANCE) && CastSpell(AVENGING_WRATH,m_bot)) { } // no gcd if (DoSupportRaid(m_bot)) { return; } //heal pets and bots if(target && target->isAlive() && HealTarget(target, target->GetHealth()*100 / target->GetMaxHealth()) ) { return; } if (ai->GetManaPercent() <= 80 && CastSpell(JOW,pTarget,true,true)) { return; } // Use Spells only if mana is sufficient.. if(ai->GetManaPercent() < offensiveSpellThreshold ) return; break; #pragma endregion #pragma region BOT_ROLE_TANK / BOT_ROLE_OFFTANK case BOT_ROLE_TANK: case BOT_ROLE_OFFTANK: ChangeAura(DEVOTION_AURA); if (CastSpell(RIGHTEOUS_FURY,m_bot)) { return; } // Choose Seal if (SOW && ai->GetManaPercent() <= 30) { if (CastSpell(SOW,m_bot)) { return; } } else if (m_bot->HasAura(SOW) && ai->GetManaPercent() < 85) { } // Paladin was striving for mana, keep until he got most of his mana back else if (SOL && ai->GetHealthPercent() < 40) { if (CastSpell(SOL,m_bot)) { return; } } else if (CastSpell(SOR,m_bot)) { return; } // We are tank/offtank threat is not an issiue; // Use taunts only if helping target is not main tank.. // Taunt if needed (Only for master) if(GetMaster()->GetGUID() != m_tank->GetGUID()) { // Taunt if needed (Only for master) Unit *curAtt = GetAttackerOf(GetMaster()); if (curAtt) { if (isUnderAttack(GetMaster(),2) && CastSpell(RIGHTEOUS_DEFENSE, GetMaster())) { return; } if (CastSpell(HOR, curAtt,true,true)) { } //No GCD } } // My target is not attacking me, taunt.. if ( m_tank->GetGUID() == m_bot->GetGUID() && pVictim && pVictim->GetGUID() != m_bot->GetGUID() && CastSpell(HOR, pTarget,true,true) ) { } //NO GCD // Tank specials if (TALENT_PROT && ai->GetManaPercent() < 90 && CastSpell (DIVINE_PLEA, m_bot)) { return; } //Prot paladin always uses this.. if (pVictim && pVictim->GetGUID() == m_bot->GetGUID() && CastSpell(HOLY_SHIELD,m_bot)) { return; } if (CastSpell(AVENGERS_SHIELD,pTarget,true,true)) { return; } if (CastSpell(HOTR,pTarget,true,true)) { return; } if (CastSpell(HOLY_WRATH,pTarget,true,true)){ return; } if (CastSpell(CONSECRATION,pTarget)) { return; } if (m_bot->getRace() == (uint8) RACE_DWARF && CastSpell(R_STONEFORM,m_bot)) { return; } if (DoSupportRaid(m_bot)) { return; } //heal pets and bots if(target && target->isAlive() && HealTarget(target, target->GetHealth()*100 / target->GetMaxHealth()) ) { return; } break; #pragma endregion #pragma region BOT_ROLE_DPS_MELEE case BOT_ROLE_DPS_MELEE: ChangeAura(RETRIBUTION_AURA); if (!TALENT_PROT && m_tank->GetGUID() != m_bot->GetGUID()) m_bot->RemoveAurasDueToSpell(RIGHTEOUS_FURY); if (CastSpell(SOV,m_bot)) { return; } if (CastSpell (HAMMER_OF_JUSTICE, pTarget)) { return; } if (!m_bot->HasAura(FORBEARANCE) && CastSpell(AVENGING_WRATH,m_bot)) {} //no gcd if (CastSpell(JOW,pTarget)) { return; } if (CastSpell(DIVINE_STORM, pTarget)) { return; } if (CastSpell(CRUSADER_STRIKE, pTarget)) { return; } if (GetAI()->GetHealthPercent(*pTarget)<20 && CastSpell(HAMMER_OF_WRATH, pTarget)) { return; } if (CastSpell(CONSECRATION,pTarget)) { return; } if (m_bot->HasAura(AOW) && CastSpell(EXORCISM,pTarget)) { return; } if (CastSpell(HOLY_WRATH,pTarget)) { return; } break; #pragma endregion } #pragma region PaladinCommon // Shared dps spells if (pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_HUMANOID && pTarget->IsNonMeleeSpellCasted(true) && CastSpell (REPENTANCE, pTarget)) { return; } if (m_bot->getRace() == (uint8) RACE_BLOODELF && pDist < 8 && pTarget->IsNonMeleeSpellCasted(true) && CastSpell(R_ARCANE_TORRENT, pTarget)) { } //no gcd if (m_bot->getRace() == (uint8) RACE_TROLL && CastSpell(R_BERSERKING,m_bot)) {} // no GCD if (m_bot->getRace() == (uint8) RACE_ORC && CastSpell(R_BLOOD_FURY,m_bot)) {} // no GCD // If at threat limit, stop if(pThreat > threatThreshold && !TALENT_PROT && m_tank->GetGUID() != m_bot->GetGUID() && !isUnderAttack()) { if (m_tank->getVictim() && m_tank->getVictim()->GetGUID() != pTarget->GetGUID()) // I am attacking wrong target!! { m_bot->SetSelection(m_tank->getVictim()->GetGUID()); return; } else { if (CastSpell(HOS,m_bot)) { return; } //Lets see if we can manage with HOS else { return; } //use no spells and wait threat to be reduced } } // Continue attacking if theres excess mana (for healers) if (m_role == BOT_ROLE_SUPPORT && ai->GetManaPercent() < offensiveSpellThreshold) { return; } if (GetAI()->GetHealthPercent(*pTarget)<20 && CastSpell(HAMMER_OF_WRATH, pTarget,true,true)) { return; } //no gcd but cast if (CastSpell (HAMMER_OF_JUSTICE, pTarget)) { return; } if (CanCast(JOW,pTarget,true) && ( ( ai->GetManaPercent() <= 70 && ai->GetHealthPercent() > 90) || ( ai->GetManaPercent() <= 50 && ai->GetHealthPercent() > 75) || ( ai->GetManaPercent() <= 20 && ai->GetHealthPercent() > 20) ) && CastSpell(JOW,pTarget,false)) { return; } else if (CastSpell(JOL,pTarget),true,true) { return; } if (CastSpell(SHIELD_OF_RIGHTEOUSNESS,pTarget,true,true)) { return; } if (CastSpell (DIVINE_STORM, pTarget,true,true)) { return; } if (CastSpell (CRUSADER_STRIKE, pTarget,true,true)) { return; } if (m_bot->getRace() == (uint8) RACE_TAUREN && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return; } //no GCD but cast if (isUnderAttack(m_tank,4) && CastSpell(HOLY_WRATH,pTarget,true,true)) { return; } if (isUnderAttack(m_tank,4) && CastSpell(CONSECRATION,pTarget)) { return; } if (CastSpell(HOLY_SHOCK,pTarget,true,true)) { return; } if (m_role != BOT_ROLE_SUPPORT && ai->GetManaPercent() > 60 && OwnPartyHP < 65 && DoSupportRaid(m_bot)) { return; } //if there is spare time and mana, do healz and other stuff.. else if (m_role != BOT_ROLE_SUPPORT && ai->GetManaPercent() > 30 && DoSupportRaid(m_bot,30,false,false,false,true,false)) { return; } if (CastSpell(EXORCISM,pTarget,true,true)) { return; } // drink potion if support / healer (Other builds simply overuse mana and waste mana pots) if(ai->GetManaPercent() < 5 && (m_role == BOT_ROLE_SUPPORT || m_role == BOT_ROLE_HEALER) ) { Item *pItem = ai->FindPotion(); if(pItem != NULL) { if (pItem->GetSpell() && m_bot->HasSpellCooldown(pItem->GetSpell()) ) { return; } //pot is in cooldown ai->UseItem(*pItem); } } #pragma endregion } //end DoNextCombatManeuver