bool PlayerbotDruidAI::HealTarget(Unit *target) { PlayerbotAI* ai = GetAI(); uint8 hp = target->GetHealth() * 100 / target->GetMaxHealth(); if (hp >= 70) return false; // Reset form if needed GoBuffForm(GetPlayerBot()); if (hp < 70 && REJUVENATION > 0 && !target->HasAura(REJUVENATION) && ai->CastSpell(REJUVENATION, *target)) return true; if (hp < 60 && LIFEBLOOM > 0 && !target->HasAura(LIFEBLOOM) && ai->CastSpell(LIFEBLOOM, *target)) return true; if (hp < 55 && REGROWTH > 0 && !target->HasAura(REGROWTH) && ai->CastSpell(REGROWTH, *target)) return true; if (hp < 50 && SWIFTMEND > 0 && (target->HasAura(REJUVENATION) || target->HasAura(REGROWTH)) && ai->CastSpell(SWIFTMEND, *target)) return true; if (hp < 45 && WILD_GROWTH > 0 && !target->HasAura(WILD_GROWTH) && ai->CastSpell(WILD_GROWTH, *target)) return true; if (hp < 30 && NOURISH > 0 && ai->CastSpell(NOURISH, *target)) return true; if (hp < 25 && HEALING_TOUCH > 0 && ai->CastSpell(HEALING_TOUCH, *target)) return true; return false; } // end HealTarget
bool PlayerbotDruidAI::HealTarget(Unit *target) { PlayerbotAI* ai = GetAI(); uint8 hp = target->GetHealth() * 100 / target->GetMaxHealth(); //If spell exists and orders say we should be dispelling if ((REMOVE_CURSE > 0 || ABOLISH_POISON > 0) && ai->GetCombatOrder() != PlayerbotAI::ORDERS_NODISPEL) { //This does something important(lol) uint32 dispelMask = GetDispellMask(DISPEL_CURSE); uint32 dispelMask2 = GetDispellMask(DISPEL_POISON); //Get a list of all the targets auras(spells affecting target) Unit::SpellAuraHolderMap const& auras = target->GetSpellAuraHolderMap(); //Iterate through the auras for (Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) { SpellAuraHolderPtr holder = itr->second; //I dont know what this does but it doesn't work without it if ((1 << holder->GetSpellProto()->Dispel) & dispelMask) { //If the spell is dispellable and we can dispel it, do so if ((holder->GetSpellProto()->Dispel == DISPEL_CURSE) & (REMOVE_CURSE > 0)) ai->CastSpell(REMOVE_CURSE, *target); return false; } else if ((1 << holder->GetSpellProto()->Dispel) & dispelMask2) { if ((holder->GetSpellProto()->Dispel == DISPEL_POISON) & (ABOLISH_POISON > 0)) ai->CastSpell(ABOLISH_POISON, *target); return false; } } } if (hp >= 70) return false; // Reset form if needed GoBuffForm(GetPlayerBot()); if (hp < 70 && REJUVENATION > 0 && !target->HasAura(REJUVENATION) && ai->CastSpell(REJUVENATION, *target)) return true; if (hp < 60 && LIFEBLOOM > 0 && !target->HasAura(LIFEBLOOM) && ai->CastSpell(LIFEBLOOM, *target)) return true; if (hp < 55 && REGROWTH > 0 && !target->HasAura(REGROWTH) && ai->CastSpell(REGROWTH, *target)) return true; if (hp < 50 && SWIFTMEND > 0 && (target->HasAura(REJUVENATION) || target->HasAura(REGROWTH)) && ai->CastSpell(SWIFTMEND, *target)) return true; if (hp < 45 && WILD_GROWTH > 0 && !target->HasAura(WILD_GROWTH) && ai->CastSpell(WILD_GROWTH, *target)) return true; if (hp < 30 && NOURISH > 0 && ai->CastSpell(NOURISH, *target)) return true; if (hp < 25 && HEALING_TOUCH > 0 && ai->CastSpell(HEALING_TOUCH, *target)) return true; return false; } // end HealTarget
CombatManeuverReturns PlayerbotDruidAI::HealPlayer(Player* target) { CombatManeuverReturns r = PlayerbotClassAI::HealPlayer(target); if (r != RETURN_NO_ACTION_OK) return r; if (!target->isAlive()) { if (m_bot->isInCombat()) { // TODO: Add check for cooldown if (REBIRTH && m_ai->In_Reach(target,REBIRTH) && m_ai->CastSpell(REBIRTH, *target)) { std::string msg = "Resurrecting "; msg += target->GetName(); m_bot->Say(msg, LANG_UNIVERSAL); return RETURN_CONTINUE; } } else { if (REVIVE && m_ai->In_Reach(target,REVIVE) && m_ai->CastSpell(REVIVE, *target)) { std::string msg = "Resurrecting "; msg += target->GetName(); m_bot->Say(msg, LANG_UNIVERSAL); return RETURN_CONTINUE; } } return RETURN_NO_ACTION_ERROR; // not error per se - possibly just OOM } //If spell exists and orders say we should be dispelling if ((REMOVE_CURSE > 0 || ABOLISH_POISON > 0) && (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_NODISPEL) == 0) { //This does something important(lol) uint32 dispelMask = GetDispellMask(DISPEL_CURSE); uint32 dispelMask2 = GetDispellMask(DISPEL_POISON); //Get a list of all the targets auras(spells affecting target) Unit::SpellAuraHolderMap const& auras = target->GetSpellAuraHolderMap(); //Iterate through the auras for (Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); itr++) { SpellAuraHolder *holder = itr->second; //I dont know what this does but it doesn't work without it if ((1 << holder->GetSpellProto()->Dispel) & dispelMask) { //If the spell is dispellable and we can dispel it, do so if ((holder->GetSpellProto()->Dispel == DISPEL_CURSE) & (REMOVE_CURSE > 0)) { if (CastSpell(REMOVE_CURSE, target)) return RETURN_CONTINUE; return RETURN_NO_ACTION_ERROR; } } else if ((1 << holder->GetSpellProto()->Dispel) & dispelMask2) { if ((holder->GetSpellProto()->Dispel == DISPEL_POISON) & (ABOLISH_POISON > 0)) { if (CastSpell(ABOLISH_POISON, target)) return RETURN_CONTINUE; return RETURN_NO_ACTION_ERROR; } } } } uint8 hp = target->GetHealthPercent(); // Everyone is healthy enough, return OK. MUST correlate to highest value below (should be last HP check) if (hp >= 90) return RETURN_NO_ACTION_OK; // Reset form if needed if (!m_bot->HasAura(TREE_OF_LIFE) || TREE_OF_LIFE == 0) GoBuffForm(GetPlayerBot()); // Start heals. Do lowest HP checks at the top if (hp < 30) { // TODO: Use in conjunction with Nature's Swiftness if (HEALING_TOUCH > 0 && m_ai->In_Reach(target,HEALING_TOUCH) && (NOURISH == 0 /*|| CastSpell(NATURES_SWIFTNESS)*/ ) && CastSpell(HEALING_TOUCH, target)) return RETURN_CONTINUE; if (NOURISH > 0 && m_ai->In_Reach(target,NOURISH) && CastSpell(NOURISH, target)) return RETURN_CONTINUE; } if (hp < 45 && WILD_GROWTH > 0 && m_ai->In_Reach(target,WILD_GROWTH) && !target->HasAura(WILD_GROWTH) && CastSpell(WILD_GROWTH, target)) return RETURN_CONTINUE; if (hp < 50 && SWIFTMEND > 0 && m_ai->In_Reach(target,SWIFTMEND) && (target->HasAura(REJUVENATION) || target->HasAura(REGROWTH)) && CastSpell(SWIFTMEND, target)) return RETURN_CONTINUE; if (hp < 60 && REGROWTH > 0 && m_ai->In_Reach(target,REGROWTH) && !target->HasAura(REGROWTH) && CastSpell(REGROWTH, target)) return RETURN_CONTINUE; if (hp < 65 && LIFEBLOOM > 0 && m_ai->In_Reach(target,LIFEBLOOM) && !target->HasAura(LIFEBLOOM) && CastSpell(LIFEBLOOM, target)) return RETURN_CONTINUE; if (hp < 90 && REJUVENATION > 0 && m_ai->In_Reach(target,REJUVENATION) && !target->HasAura(REJUVENATION) && CastSpell(REJUVENATION, target)) return RETURN_CONTINUE; return RETURN_NO_ACTION_UNKNOWN; } // end HealTarget
CombatManeuverReturns PlayerbotDruidAI::HealPlayer(Player* target) { CombatManeuverReturns r = PlayerbotClassAI::HealPlayer(target); if (r != RETURN_NO_ACTION_OK) return r; if (!target->isAlive()) { if (m_bot->isInCombat()) { if (REBIRTH && m_ai->In_Reach(target, REBIRTH) && m_bot->IsSpellReady(REBIRTH) && m_ai->CastSpell(REBIRTH, *target)) { std::string msg = "Resurrecting "; msg += target->GetName(); m_bot->Say(msg, LANG_UNIVERSAL); return RETURN_CONTINUE; } } return RETURN_NO_ACTION_ERROR; // not error per se - possibly just OOM } // Remove curse on group members if orders allow bot to do so if (Player* pCursedTarget = GetDispelTarget(DISPEL_CURSE)) { if (REMOVE_CURSE > 0 && (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_NODISPEL) == 0 && CastSpell(REMOVE_CURSE, pCursedTarget)) return RETURN_CONTINUE; } // Remove poison on group members if orders allow bot to do so if (Player* pPoisonedTarget = GetDispelTarget(DISPEL_POISON)) { uint32 cure = ABOLISH_POISON > 0 ? ABOLISH_POISON : CURE_POISON; if (cure > 0 && (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_NODISPEL) == 0 && CastSpell(cure, pPoisonedTarget)) return RETURN_CONTINUE; } uint8 hp = target->GetHealthPercent(); // Define a tank bot will look at Unit* pMainTank = GetHealTarget(JOB_TANK); // If target is out of range (40 yards) and is a tank: move towards it // Other classes have to adjust their position to the healers // TODO: This code should be common to all healers and will probably // move to a more suitable place if (pMainTank && !m_ai->In_Reach(pMainTank, HEALING_TOUCH)) { m_bot->GetMotionMaster()->MoveFollow(target, 39.0f, m_bot->GetOrientation()); return RETURN_CONTINUE; } // Everyone is healthy enough, return OK. MUST correlate to highest value below (should be last HP check) if (hp >= 80) return RETURN_NO_ACTION_OK; // Reset form if needed if (!m_bot->HasAura(TREE_OF_LIFE) || TREE_OF_LIFE == 0) GoBuffForm(GetPlayerBot()); // Start heals. Do lowest HP checks at the top // Emergency heal: target needs to be healed NOW! if ((target == pMainTank && hp < 10) || (target != pMainTank && hp < 15)) { // first try Nature's Swiftness + Healing Touch: instant heal if (NATURES_SWIFTNESS > 0 && m_bot->IsSpellReady(NATURES_SWIFTNESS) && CastSpell(NATURES_SWIFTNESS, m_bot)) return RETURN_CONTINUE; if (HEALING_TOUCH > 0 && m_bot->HasAura(NATURES_SWIFTNESS, EFFECT_INDEX_0) && m_ai->In_Reach(target, HEALING_TOUCH) && CastSpell(HEALING_TOUCH, target)) return RETURN_CONTINUE; // Else try to Swiftmend the target if druid HoT is active on it if (SWIFTMEND > 0 && m_bot->IsSpellReady(SWIFTMEND) && m_ai->In_Reach(target, SWIFTMEND) && (target->HasAura(REJUVENATION) || target->HasAura(REGROWTH)) && CastSpell(SWIFTMEND, target)) return RETURN_CONTINUE; } // Urgent heal: target won't die next second, but first bot needs to gain some time to cast Healing Touch safely if ((target == pMainTank && hp < 15) || (target != pMainTank && hp < 25)) { if (REGROWTH > 0 && m_ai->In_Reach(target, REGROWTH) && !target->HasAura(REGROWTH) && CastSpell(REGROWTH, target)) return RETURN_CONTINUE; if (REJUVENATION > 0 && m_ai->In_Reach(target, REJUVENATION) && target->HasAura(REGROWTH) && !target->HasAura(REJUVENATION) && CastSpell(REJUVENATION, target)) return RETURN_CONTINUE; if (SWIFTMEND > 0 && m_bot->IsSpellReady(SWIFTMEND) && m_ai->In_Reach(target, SWIFTMEND) && (target->HasAura(REJUVENATION) || target->HasAura(REGROWTH)) && CastSpell(SWIFTMEND, target)) return RETURN_CONTINUE; } if (hp < 60 && HEALING_TOUCH > 0 && m_ai->In_Reach(target, HEALING_TOUCH) && CastSpell(HEALING_TOUCH, target)) return RETURN_CONTINUE; if (hp < 65 && LIFEBLOOM > 0 && m_ai->In_Reach(target, LIFEBLOOM) && !target->HasAura(LIFEBLOOM) && CastSpell(LIFEBLOOM, target)) return RETURN_CONTINUE; if (hp < 80 && REJUVENATION > 0 && m_ai->In_Reach(target, REJUVENATION) && !target->HasAura(REJUVENATION) && CastSpell(REJUVENATION, target)) return RETURN_CONTINUE; return RETURN_NO_ACTION_UNKNOWN; } // end HealTarget