void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) return; while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { case EVENT_SHADOW_WORD_PAIN: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) DoCast(target, SPELL_SHADOW_WORD_PAIN); events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); return; case EVENT_CIRCLE_OF_DESTRUCTION: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) DoCast(target, SPELL_CIRCLE_OF_DESTRUCTION); events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); return; case EVENT_COWER_IN_FEAR: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) DoCast(target, SPELL_COWER_IN_FEAR); events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); return; case EVENT_DARK_MENDING: // find an ally with missing HP if (Unit* target = DoSelectLowestHpFriendly(40, DUNGEON_MODE(30000, 50000))) { DoCast(target, SPELL_DARK_MENDING); events.ScheduleEvent(EVENT_DARK_MENDING, 20000); } else { // no friendly unit with missing hp. re-check in just 5 sec. events.ScheduleEvent(EVENT_DARK_MENDING, 5000); } return; } } DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; if (uiShieldTimer <= diff) { me->AddAura(RAND(SPELL_MAGIC_REFLECTION, SPELL_DAMAGE_REFLECTION), me); // DoCast(m_creature, RAND(SPELL_MAGIC_REFLECTION, SPELL_DAMAGE_REFLECTION)); uiShieldTimer = urand(20000, 30000); } else uiShieldTimer -= diff; switch (me->GetEntry()) { case NPC_FLAMEWAKER_ELITE: if (Blastwave_Timer <= diff) { DoCast(SPELL_BLAST_WAVE); Blastwave_Timer = 10000; } else Blastwave_Timer -= diff; if (uiFireBlastTimer <= diff) { DoCast(SPELL_FIRE_BLAST); uiFireBlastTimer = 15000; } else uiFireBlastTimer -= diff; break; case NPC_FLAMEWAKER_HEALER: if (uiShadowShockTimer <= diff) { if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) DoCast(pTarget, SPELL_SHADOW_SHOCK); uiShadowShockTimer = 2000; } else uiShadowShockTimer -= diff; if (uiHealTimer <= diff) { if (Unit* pTarget = DoSelectLowestHpFriendly(200)) DoCast(pTarget, SPELL_HEAL_BRETHREN); uiHealTimer = urand(15000, 20000); } else uiHealTimer -= diff; break; } DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; events.Update(diff); while (uint32 eventId = events.ExecuteEvent()) { switch(eventId) { case EVENT_ENRAGE: DoScriptText(SAY_MOLGEIM_BERSERK, me); DoCast(SPELL_BERSERK); break; case EVENT_RUNE_OF_POWER: // Improve target selection; random alive friendly { Unit *pTarget = DoSelectLowestHpFriendly(60); if (!pTarget || !pTarget->isAlive()) pTarget = me; DoCast(pTarget, SPELL_SUMMON_RUNE_OF_POWER); events.ScheduleEvent(EVENT_RUNE_OF_POWER, 60000); break; } case EVENT_SHIELD_OF_RUNES: DoCast(me, RAID_MODE(SPELL_SHIELD_OF_RUNES, SPELL_SHIELD_OF_RUNES_H)); events.ScheduleEvent(EVENT_SHIELD_OF_RUNES, urand(27000,34000)); break; case EVENT_RUNE_OF_DEATH: DoScriptText(SAY_MOLGEIM_RUNE_DEATH, me); if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) DoCast(pTarget, SPELL_RUNE_OF_DEATH); events.ScheduleEvent(EVENT_RUNE_OF_DEATH, urand(30000,40000)); break; case EVENT_RUNE_OF_SUMMONING: DoScriptText(SAY_MOLGEIM_SUMMON, me); if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) DoCast(pTarget, SPELL_RUNE_OF_SUMMONING); events.ScheduleEvent(EVENT_RUNE_OF_SUMMONING, urand(20000,30000)); break; } } DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 uiDiff) { if (!UpdateVictim()) return; if (me->HasUnitState(UNIT_STAT_CASTING)) return; //Chain heal Timer if (m_uiHealTimer <= uiDiff) { if (Unit *pAlly = DoSelectLowestHpFriendly(INTERACTION_DISTANCE*100)) DoCast(pAlly, SPELL_HEAL); m_uiHealTimer = urand(15000, 20000); } else m_uiHealTimer -= uiDiff; //Fel Fireball Timer if (m_uiFFireballTimer <= uiDiff) { if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) DoCast(pTarget, SPELL_FEL_FIREBALL); m_uiFFireballTimer = urand(10000, 15000); } else m_uiFFireballTimer -= uiDiff; //Fire Nova timer if (m_uiFireNovaTimer <= uiDiff) { DoCast(me, SPELL_FIRE_NOVA); m_uiFireNovaTimer = urand(8000, 15000); } else m_uiFireNovaTimer -= uiDiff; DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; // Casting Heal to Sulfuron or other Guards. if (m_uiHealTimer < uiDiff) { if (Unit* pUnit = DoSelectLowestHpFriendly(60.0f, 1)) { if (DoCastSpellIfCan(pUnit, SPELL_HEAL) == CAST_OK) m_uiHealTimer = urand(15000, 20000); } } else m_uiHealTimer -= uiDiff; // ShadowWord Pain Timer if (m_uiShadowWordPainTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_SHADOWWORD_PAIN) == CAST_OK) m_uiShadowWordPainTimer = urand(18000, 26000); } } else m_uiShadowWordPainTimer -= uiDiff; // Immolate Timer if (m_uiImmolateTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_IMMOLATE) == CAST_OK) m_uiImmolateTimer = urand(15000, 25000); } } else m_uiImmolateTimer -= uiDiff; DoMeleeAttackIfReady(); }
bool UpdateChampionAI(const uint32 uiDiff) { if (m_uiLightningTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_CHAIN_LIGHTNING) == CAST_OK) m_uiLightningTimer = urand(1000, 3000); } else m_uiLightningTimer -= uiDiff; if (m_uiHealingWaveTimer < uiDiff) { if (Unit* pTarget = DoSelectLowestHpFriendly(40.0f)) { if (DoCastSpellIfCan(pTarget, SPELL_HEALING_WAVE) == CAST_OK) m_uiHealingWaveTimer = urand(8000, 13000); } } else m_uiHealingWaveTimer -= uiDiff; if (m_uiEarthShieldTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_EARTH_SHIELD, CAST_AURA_NOT_PRESENT) == CAST_OK) m_uiEarthShieldTimer = 30000; else m_uiEarthShieldTimer = 5000; } else m_uiEarthShieldTimer -= uiDiff; if (m_uiHexTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_HEX_OF_MENDING) == CAST_OK) m_uiHexTimer = urand(17000, 25000); } else m_uiHexTimer -= uiDiff; return true; }
void UpdateEscortAI(const uint32 uiDiff) override { DialogueUpdate(uiDiff); if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (m_uiExorcismTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_EXORCISM : SPELL_EXORCISM_H) == CAST_OK) m_uiExorcismTimer = urand(9000, 13000); } else m_uiExorcismTimer -= uiDiff; if (m_uiHolyLightTimer < uiDiff) { if (Unit* pTarget = DoSelectLowestHpFriendly(40.0f)) { if (DoCastSpellIfCan(pTarget, SPELL_HOLY_LIGHT) == CAST_OK) m_uiHolyLightTimer = urand(18000, 25000); } } else m_uiHolyLightTimer -= uiDiff; if (!m_bYell50Pct && m_creature->GetHealthPercent() < 50.0f) { DoScriptText(SAY_ARTHAS_HALF_HP, m_creature); m_bYell50Pct = true; } if (!m_bYell20Pct && m_creature->GetHealthPercent() < 20.0f) { DoScriptText(SAY_ARTHAS_LOW_HP, m_creature); m_bYell20Pct = true; } DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; //Casting Heal to Sulfuron or other Guards. if (Heal_Timer <= diff) { Unit* pUnit = DoSelectLowestHpFriendly(60.0f, 1); if (!pUnit) return; DoCast(pUnit, SPELL_HEAL); Heal_Timer = 15000+rand()%5000; } else Heal_Timer -= diff; //ShadowWordPain_Timer if (ShadowWordPain_Timer <= diff) { Unit *pTarget = NULL; pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); if (pTarget) DoCast(pTarget, SPELL_SHADOWWORDPAIN); ShadowWordPain_Timer = 18000+rand()%8000; } else ShadowWordPain_Timer -= diff; //Immolate_Timer if (Immolate_Timer <= diff) { Unit *pTarget = NULL; pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); if (pTarget) DoCast(pTarget, SPELL_IMMOLATE); Immolate_Timer = 15000+rand()%10000; } else Immolate_Timer -= diff; DoMeleeAttackIfReady(); }
void PlayerbotPaladinAI::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_STATE_CASTING)) { return; } if (m_bot->getStandState() == UNIT_STAND_STATE_SIT) { return; } //buff and heal raid 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; } //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 (m_bot->GetHealth() < m_bot->GetMaxHealth() && CastSpell(FLASH_OF_LIGHT,m_bot)) { return; } if (ai->GetManaPercent() < 70) { ai->Feast(); } } //end DoNonCombatActions
bool PlayerbotShamanAI::HealGroup (Unit *target, uint8 hp, uint8 &countNeedHeal) { Player *m_bot = GetPlayerBot(); if (countNeedHeal < 2) { return false; } Unit *rTarget = DoSelectLowestHpFriendly(30,500); if (!rTarget || rTarget->isDead() || rTarget->GetHealth() * 100 / rTarget->GetMaxHealth() > 80 ) { return false; } if (hp < 65 && RIPTIDE && rTarget->HasAura(RIPTIDE,m_bot->GetGUID()) && CastSpell(CHAIN_HEAL, rTarget)) { return true; } if (hp < 85 && CastSpell(RIPTIDE, rTarget)) { return true; } if (hp < 75 && CastSpell(CHAIN_HEAL, rTarget,true,true)) { return true; } return false; }
void UpdateAI(const uint32 diff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; //cast bubble at 20% hp if (m_creature->GetHealthPercent() < 20.0f) timedCast(SPELL_BUBBLE, diff); if (Unit *target = DoSelectLowestHpFriendly(40.0f)) if (target->GetHealthPercent() < 15.0f) timedCast(SPELL_HAND_OF_PROTECTION, diff); timedCast(SPELL_HOLY_SHOCK, diff); if (Unit *target = SelectRandomFriendlyMissingBuff(SPELL_HAND_OF_FREEDOM)) timedCast(SPELL_HAND_OF_FREEDOM, diff, target); timedCast(SPELL_HAMMER_OF_JUSTICE, diff); if (timedQuery(SPELL_FLASH_OF_LIGHT, diff)) { switch (urand(0,4)) { case 0: case 1: doCast(SPELL_FLASH_OF_LIGHT); break; case 2: case 3: doCast(SPELL_HOLY_LIGHT); break; case 4: doCast(SPELL_CLEANSE); break; } } boss_faction_championsAI::UpdateAI(diff); }
void UpdateAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (m_uiHealTimer <= uiDiff) { if (Unit* pTarget = DoSelectLowestHpFriendly(50.0f)) { if (DoCastSpellIfCan(pTarget, SPELL_SOLARIUM_GREAT_HEAL) == CAST_OK) m_uiHealTimer = 9000; } } else m_uiHealTimer -= uiDiff; if (m_uiHolySmiteTimer <= uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, nullptr, SELECT_FLAG_PLAYER)) { if (DoCastSpellIfCan(pTarget, SPELL_SOLARIUM_HOLY_SMITE) == CAST_OK) m_uiHolySmiteTimer = 4000; } } else m_uiHolySmiteTimer -= uiDiff; if (m_uiAoESilenceTimer <= uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_SOLARIUM_ARCANE_TORRENT) == CAST_OK) m_uiAoESilenceTimer = 13000; } else m_uiAoESilenceTimer -= uiDiff; DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; events.Update(diff); if (me->HasUnitState(UNIT_STAT_CASTING)) return; while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { case EVENT_HEAL: if (Unit* target = DoSelectLowestHpFriendly(60.0f, 1)) DoCast(target, SPELL_HEAL); events.ScheduleEvent(EVENT_HEAL, urand(15000, 20000)); break; case EVENT_SHADOW_WORD_PAIN: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_SHADOWWORDPAIN)) DoCast(target, SPELL_SHADOWWORDPAIN); events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(18000, 26000)); break; case EVENT_IMMOLATE: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_IMMOLATE)) DoCast(target, SPELL_IMMOLATE); events.ScheduleEvent(EVENT_IMMOLATE, urand(15000, 25000)); break; default: break; } } DoMeleeAttackIfReady(); }
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
CanCastResult BSWScriptedAI::_BSWSpellSelector(uint8 m_uiSpellIdx, Unit* pTarget) { BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx]; Unit* pSummon = NULL; CanCastResult result = CAST_FAIL_OTHER; debug_log("BSW: Casting spell number %u type %u",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget); if (pSpell->m_uiSpellTimerMax[currentDifficulty] >= HOUR*IN_MILLISECONDS) m_creature->InterruptNonMeleeSpells(true); switch (pSpell->m_CastTarget) { case DO_NOTHING: result = CAST_OK; break; case CAST_ON_SELF: result = _BSWCastOnTarget(m_creature, m_uiSpellIdx); break; case CAST_ON_SUMMONS: result = _BSWCastOnTarget(pTarget, m_uiSpellIdx); break; case CAST_ON_VICTIM: pTarget = m_creature->getVictim(); result = _BSWCastOnTarget(pTarget, m_uiSpellIdx); break; case CAST_ON_RANDOM: pTarget = _doSelect(0, false, 60.0f); result = _BSWCastOnTarget(pTarget, m_uiSpellIdx); break; case CAST_ON_BOTTOMAGGRO: pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_BOTTOMAGGRO,0); result = _BSWCastOnTarget(pTarget, m_uiSpellIdx); break; case CAST_ON_TARGET: result = _BSWCastOnTarget(pTarget, m_uiSpellIdx); break; case APPLY_AURA_SELF: if (_doAura(m_uiSpellIdx, m_creature, EFFECT_INDEX_0)) result = CAST_OK; else result = CAST_FAIL_OTHER; break; case APPLY_AURA_TARGET: if (!pTarget || !pTarget->IsInMap(m_creature)) { result = CAST_FAIL_OTHER; break; } if (_doAura(m_uiSpellIdx, pTarget, EFFECT_INDEX_0)) result = CAST_OK; else result = CAST_FAIL_OTHER; break; case SUMMON_NORMAL: pSummon = _doSummon(m_uiSpellIdx, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); if(pSummon) result = CAST_OK; else result = CAST_FAIL_OTHER; break; case SUMMON_TEMP: pSummon = _doSummon(m_uiSpellIdx, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, urand(pSpell->m_uiSpellTimerMin[currentDifficulty],pSpell->m_uiSpellTimerMax[currentDifficulty])); if(pSummon) result = CAST_OK; else result = CAST_FAIL_OTHER; break; case SUMMON_INSTANT: pSummon = _doSummon(m_uiSpellIdx, TEMPSUMMON_MANUAL_DESPAWN,0); if(pSummon) result = CAST_OK; else result = CAST_FAIL_OTHER; break; case CAST_ON_ALLPLAYERS: { Map* pMap = m_creature->GetMap(); Map::PlayerList const& pPlayers = pMap->GetPlayers(); if (!pPlayers.isEmpty()) { for (Map::PlayerList::const_iterator itr = pPlayers.begin(); itr != pPlayers.end(); ++itr) { pTarget = itr->getSource(); if (pTarget && pTarget->isAlive() && pTarget->IsWithinDistInMap(m_creature, pSpell->LocData.x)) { if (!pSpell->m_IsBugged) { m_creature->CastSpell(pTarget, pSpell->m_uiSpellEntry[currentDifficulty], false); } else { _BSWDoCast(m_uiSpellIdx, pTarget); }; result = CAST_OK; }; } } else result = CAST_FAIL_OTHER; } break; case CAST_ON_FRENDLY: pTarget = DoSelectLowestHpFriendly(pSpell->LocData.x,0); result = _BSWCastOnTarget(pTarget, m_uiSpellIdx); break; case CAST_ON_FRENDLY_LOWHP: pTarget = DoSelectLowestHpFriendly(pSpell->LocData.x,1); result = _BSWCastOnTarget(pTarget, m_uiSpellIdx); break; case CAST_ON_RANDOM_POINT: if (!pTarget) pTarget = m_creature; if (pSpell->LocData.z <= 1.0f) { float fPosX, fPosY, fPosZ; if (!pTarget->IsPositionValid() || !pTarget->IsInMap(m_creature)) { if (pTarget->GetTypeId() == TYPEID_PLAYER) error_log("BSW: CAST_ON_RANDOM_POINT FAILED: player has invalid position. SpellID is %u",pSpell->m_uiSpellEntry[currentDifficulty]); else error_log("BSW: CAST_ON_RANDOM_POINT FAILED: creature has invalid position. SpellID is %u",pSpell->m_uiSpellEntry[currentDifficulty]); result = CAST_FAIL_OTHER; break; } pTarget->GetPosition(fPosX, fPosY, fPosZ); pTarget->GetRandomPoint(fPosX, fPosY, fPosZ, urand((uint32)pSpell->LocData.x, (uint32)pSpell->LocData.y), fPosX, fPosY, fPosZ); if ((int)fPosZ == 0) { error_log("BSW: CAST_ON_RANDOM_POINT FAILED: Positon Z is NULL. Strange bug"); result = CAST_FAIL_OTHER; break; } if (SpellEntry const *spell = (SpellEntry *)GetSpellStore()->LookupEntry(pSpell->m_uiSpellEntry[currentDifficulty])) if (SpellRangeEntry const *pSpellRange = GetSpellRangeStore()->LookupEntry(spell->rangeIndex)) if (m_creature->GetDistance(fPosX, fPosY, fPosZ) <= pSpellRange->maxRange) { m_creature->CastSpell(fPosX, fPosY, fPosZ, pSpell->m_uiSpellEntry[currentDifficulty], false); result = CAST_OK; break; }; result = CAST_FAIL_TOO_FAR; } else result = CAST_FAIL_OTHER; break; case CAST_ON_RANDOM_PLAYER: if ( pSpell->LocData.x < 1 ) pTarget = _doSelect(0, false, 60.0f); else pTarget = _doSelect(0, false, (float)pSpell->LocData.x); result = _BSWCastOnTarget(pTarget, m_uiSpellIdx); break; case APPLY_AURA_ALLPLAYERS: { Map* pMap = m_creature->GetMap(); Map::PlayerList const& pPlayers = pMap->GetPlayers(); for (Map::PlayerList::const_iterator itr = pPlayers.begin(); itr != pPlayers.end(); ++itr) { pTarget = itr->getSource(); if (pTarget && pTarget->isAlive() && pTarget->IsWithinDistInMap(m_creature, pSpell->LocData.x)) { _doAura(m_uiSpellIdx, pTarget, EFFECT_INDEX_0); result = CAST_OK; } } } break; case FORCE_CAST: result = _BSWDoForceCast(m_uiSpellIdx, pTarget); break; case SPELLTABLEPARM_NUMBER: default: error_log("BSW: FAILED casting spell number %u type %u - type not exists",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget); result = CAST_FAIL_OTHER; break; }; if (pSpell->textEntry && result == CAST_OK) { if (pTarget) DoScriptText(pSpell->textEntry,m_creature,pTarget); else DoScriptText(pSpell->textEntry,m_creature); }; debug_log("BSW: Casted spell number %u, result = %u",pSpell->m_uiSpellEntry[currentDifficulty], result); return result; };
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
void UpdateAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (m_uiBlessingTimer < uiDiff) { if (Unit* pTarget = DoSelectLowestHpFriendly(80.0f)) { if (DoCastSpellIfCan(pTarget, urand(0, 1) ? SPELL_BLESS_SPELLWARD : SPELL_BLESS_PROTECTION) == CAST_OK) m_uiBlessingTimer = 60000; } } else m_uiBlessingTimer -= uiDiff; if (m_uiConsecrationTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_CONSECRATION) == CAST_OK) m_uiConsecrationTimer = urand(10000, 15000); } else m_uiConsecrationTimer -= uiDiff; if (m_uiHammerOfJusticeTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, SPELL_HAMMER_OF_JUSTICE, SELECT_FLAG_PLAYER | SELECT_FLAG_NOT_IN_MELEE_RANGE)) { if (DoCastSpellIfCan(pTarget, SPELL_HAMMER_OF_JUSTICE) == CAST_OK) m_uiHammerOfJusticeTimer = 20000; } } else m_uiHammerOfJusticeTimer -= uiDiff; if (m_uiSealTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, urand(0, 1) ? SPELL_SEAL_OF_COMMAND : SPELL_SEAL_OF_BLOOD) == CAST_OK) { m_uiSealTimer = 40000; if (urand(0, 1)) m_uiJudgmentTimer = urand(4000, 7000); } } else m_uiSealTimer -= uiDiff; if (m_uiAuraTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, urand(0, 1) ? SPELL_DEVOTION_AURA : SPELL_CHROMATIC_AURA) == CAST_OK) m_uiAuraTimer = 90000; } else m_uiAuraTimer -= uiDiff; if (m_uiJudgmentTimer) { if (m_uiJudgmentTimer <= uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_JUDGMENT) == CAST_OK) m_uiJudgmentTimer = 0; } else m_uiJudgmentTimer -= uiDiff; } DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 uiDiff) override { // spawn Romulo on timer after fake death if (m_uiSummonRomuloTimer) { if (m_uiSummonRomuloTimer <= uiDiff) { m_creature->SummonCreature(NPC_ROMULO, afRomuloSpawnLoc[0], afRomuloSpawnLoc[1], afRomuloSpawnLoc[2], afRomuloSpawnLoc[3], TEMPSUMMON_DEAD_DESPAWN, 0); m_uiSummonRomuloTimer = 0; } else m_uiSummonRomuloTimer -= uiDiff; } if (m_uiResurrectSelfTimer) { if (m_uiResurrectSelfTimer <= uiDiff) { if (m_pInstance) { if (Creature* pRomulo = m_pInstance->GetSingleCreatureFromStorage(NPC_ROMULO)) { // if Romulos is dead, then self kill if (pRomulo->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) { m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); pRomulo->DealDamage(pRomulo, pRomulo->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); } else { DoRemoveFakeDeath(); DoCastSpellIfCan(m_creature, SPELL_FULL_HEALTH, CAST_TRIGGERED); } } } m_uiResurrectSelfTimer = 0; } else m_uiResurrectSelfTimer -= uiDiff; } if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; // don't use spells during transition if (m_bIsFakingDeath) return; if (m_uiBlindingPassionTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_BLINDING_PASSION) == CAST_OK) m_uiBlindingPassionTimer = urand(30000, 45000); } } else m_uiBlindingPassionTimer -= uiDiff; if (m_uiDevotionTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_DEVOTION) == CAST_OK) m_uiDevotionTimer = urand(15000, 45000); } else m_uiDevotionTimer -= uiDiff; if (m_uiPowerfulAttractionTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_POWERFUL_ATTRACTION) == CAST_OK) m_uiPowerfulAttractionTimer = urand(5000, 30000); } } else m_uiPowerfulAttractionTimer -= uiDiff; if (m_uiEternalAffectionTimer < uiDiff) { if (Unit* pTarget = DoSelectLowestHpFriendly(30.0f)) { if (DoCastSpellIfCan(pTarget, SPELL_ETERNAL_AFFECTION) == CAST_OK) m_uiEternalAffectionTimer = urand(45000, 60000); } } else m_uiEternalAffectionTimer -= uiDiff; DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if (isInMountedGauntlet()) { npc_mounted_championAI::UpdateAI(diff); return; } if (!UpdateVictim()) return; if(defeated) return; if(me->HasUnitState(UNIT_STATE_CASTING)) return; if (chainLightningTimer <= diff) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) DoCast(target, SPELL_CHAIN_LIGHTNING); chainLightningTimer = 8000; } else chainLightningTimer -= diff; if (healingWaveTimer <= diff) { bool chance = urand(0, 1); if(!chance) { if (Unit* friendUnit = DoSelectLowestHpFriendly(40)) { DoCast(friendUnit, SPELL_HEALING_WAVE); healingWaveTimer = 5000; } }else { DoCast(me, SPELL_HEALING_WAVE); healingWaveTimer = 8000; } } else healingWaveTimer -= diff; if (eartShieldTimer <= diff) { Unit* friendUnit = DoSelectLowestHpFriendly(40); if (friendUnit && friendUnit->HealthBelowPct(60) && !friendUnit->HasAura(SPELL_EARTH_SHIELD)) { DoCast(friendUnit, SPELL_EARTH_SHIELD); eartShieldTimer = urand(30000, 35000); }else if(!me->HasAura(SPELL_EARTH_SHIELD)) { DoCast(me, SPELL_EARTH_SHIELD); eartShieldTimer = urand(30000, 35000); } else eartShieldTimer = urand(1500, 3500); } else eartShieldTimer -= diff; if (hexMendingTimer <= diff) { DoCastVictim(SPELL_HEX_OF_MENDING, true); hexMendingTimer = urand(12000, 15000); } else hexMendingTimer -= diff; DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 uiDiff) { if (!bDone && GrandChampionsOutVehicle(me)) { bDone = true; if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_1)) me->SetHomePosition(739.678f, 662.541f, 412.393f, 4.49f); else if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_2)) me->SetHomePosition(746.71f, 661.02f, 411.69f, 4.6f); else if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_3)) me->SetHomePosition(754.34f, 660.70f, 412.39f, 4.79f); if (instance) instance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); EnterEvadeMode(); bHome = true; } if (uiPhaseTimer <= uiDiff) { if (uiPhase == 1) { AggroAllPlayers(me); uiPhase = 0; } }else uiPhaseTimer -= uiDiff; if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) return; if (uiChainLightningTimer <= uiDiff) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) DoCast(target, SPELL_CHAIN_LIGHTNING); uiChainLightningTimer = 16000; } else uiChainLightningTimer -= uiDiff; if (uiHealingWaveTimer <= uiDiff) { bool bChance = urand(0, 1); if (!bChance) { if (Unit* pFriend = DoSelectLowestHpFriendly(40)) DoCast(pFriend, SPELL_HEALING_WAVE); } else DoCast(me, SPELL_HEALING_WAVE); uiHealingWaveTimer = 12000; } else uiHealingWaveTimer -= uiDiff; if (uiEartShieldTimer <= uiDiff) { DoCast(me, SPELL_EARTH_SHIELD); uiEartShieldTimer = urand(30000, 35000); } else uiEartShieldTimer -= uiDiff; if (uiHexMendingTimer <= uiDiff) { DoCastVictim(SPELL_HEX_OF_MENDING, true); uiHexMendingTimer = urand(20000, 25000); } else uiHexMendingTimer -= uiDiff; DoMeleeAttackIfReady(); }
void UpdateEscortAI(const uint32 uiDiff) override { DialogueUpdate(uiDiff); if (m_uiOutroTimer) { if (m_uiOutroTimer <= uiDiff) { switch (m_uiOutroPhase) { case 0: DoScriptText(SAY_REMULOS_OUTRO_1, m_creature); m_uiOutroTimer = 3000; break; case 1: // Despawn Remulos after the outro is finished - he will respawn automatically at his home position after a few min DoScriptText(SAY_REMULOS_OUTRO_2, m_creature); m_creature->SetRespawnDelay(1 * MINUTE); m_creature->ForcedDespawn(3000); m_uiOutroTimer = 0; break; } ++m_uiOutroPhase; } else m_uiOutroTimer -= uiDiff; } // during the battle if (m_uiShadesummonTimer) { if (m_uiShadesummonTimer <= uiDiff) { // do this yell only first time if (m_bIsFirstWave) { // summon 3 shades inside the house for (uint8 i = 0; i < MAX_SHADOWS; ++i) m_creature->SummonCreature(NPC_NIGHTMARE_PHANTASM, aShadowsLocations[i].m_fX, aShadowsLocations[i].m_fY, aShadowsLocations[i].m_fZ, 0, TEMPSPAWN_DEAD_DESPAWN, 0); if (Creature* pEranikus = m_creature->GetMap()->GetCreature(m_eranikusGuid)) DoScriptText(SAY_ERANIKUS_ATTACK_1, pEranikus); ++m_uiSummonCount; SetEscortPaused(false); m_bIsFirstWave = false; } // Summon 3 shades per turn until the maximum summon turns are reached float fX, fY, fZ; // Randomize the summon point uint8 uiSummonPoint = roll_chance_i(70) ? uint32(MAX_SHADOWS) : urand(MAX_SHADOWS + 1, MAX_SHADOWS + 2); if (m_uiSummonCount < MAX_SUMMON_TURNS) { for (uint8 i = 0; i < MAX_SHADOWS; ++i) { m_creature->GetRandomPoint(aShadowsLocations[uiSummonPoint].m_fX, aShadowsLocations[uiSummonPoint].m_fY, aShadowsLocations[uiSummonPoint].m_fZ, 10.0f, fX, fY, fZ); m_creature->SummonCreature(NPC_NIGHTMARE_PHANTASM, fX, fY, fZ, 0.0f, TEMPSPAWN_DEAD_DESPAWN, 0); } ++m_uiSummonCount; } // If all the shades were summoned then set Eranikus in combat // We don't count the dead shades, because the boss is usually set in combat before all shades are dead if (m_uiSummonCount == MAX_SUMMON_TURNS) { m_uiShadesummonTimer = 0; if (Creature* pEranikus = m_creature->GetMap()->GetCreature(m_eranikusGuid)) { pEranikus->SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0); pEranikus->SetLevitate(false); pEranikus->GetMotionMaster()->MovePoint(POINT_ID_ERANIKUS_COMBAT, aEranikusLocations[2].m_fX, aEranikusLocations[2].m_fY, aEranikusLocations[2].m_fZ); } } else m_uiShadesummonTimer = urand(20000, 30000); } else m_uiShadesummonTimer -= uiDiff; } // Combat spells if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (m_uiHealTimer < uiDiff) { if (Unit* pTarget = DoSelectLowestHpFriendly(DEFAULT_VISIBILITY_DISTANCE)) { switch (urand(0, 2)) { case 0: DoCastSpellIfCan(pTarget, SPELL_HEALING_TOUCH); break; case 1: DoCastSpellIfCan(pTarget, SPELL_REJUVENATION); break; case 2: DoCastSpellIfCan(pTarget, SPELL_REGROWTH); break; } } m_uiHealTimer = 10000; } else m_uiHealTimer -= uiDiff; if (m_uiStarfireTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_STARFIRE) == CAST_OK) m_uiStarfireTimer = 20000; } } else m_uiStarfireTimer -= uiDiff; DoMeleeAttackIfReady(); }
void UpdateEscortAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; // start event epilog if (!m_bTirionSpawned && m_creature->GetHealthPercent() < 20.0f) { if (Creature* pTaelan = m_creature->GetMap()->GetCreature(m_taelanGuid)) SendAIEvent(AI_EVENT_CUSTOM_B, m_creature, pTaelan); m_bTirionSpawned = true; } // combat spells if (m_uiMindBlastTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_MIND_BLAST) == CAST_OK) m_uiMindBlastTimer = urand(3000, 5000); } else m_uiMindBlastTimer -= uiDiff; if (m_uiMindFlayTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_MIND_FLAY) == CAST_OK) m_uiMindFlayTimer = urand(9000, 15000); } else m_uiMindFlayTimer -= uiDiff; if (m_uiManaBurnTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_MANA_BURN) == CAST_OK) m_uiManaBurnTimer = urand(8000, 12000); } else m_uiManaBurnTimer -= uiDiff; if (m_uiDominateTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1, SPELL_DOMINATE_MIND, SELECT_FLAG_PLAYER)) { if (DoCastSpellIfCan(pTarget, SPELL_DOMINATE_MIND) == CAST_OK) m_uiDominateTimer = urand(25000, 30000); } } else m_uiDominateTimer -= uiDiff; if (m_uFlashHealTimer < uiDiff) { if (Unit* pTarget = DoSelectLowestHpFriendly(50.0f)) { if (DoCastSpellIfCan(pTarget, SPELL_FLASH_HEAL) == CAST_OK) m_uFlashHealTimer = urand(10000, 15000); } } else m_uFlashHealTimer -= uiDiff; if (m_creature->GetHealthPercent() < 50.0f) { if (m_uiGreaterHealTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_GREATER_HEAL) == CAST_OK) m_uiGreaterHealTimer = urand(15000, 20000); } else m_uiGreaterHealTimer -= uiDiff; } DoMeleeAttackIfReady(); }
bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& holder, Unit* actionInvoker /*=NULL*/) { if (!holder.Enabled || holder.Time) return false; //Check the inverse phase mask (event doesn't trigger if current phase bit is set in mask) if (holder.Event.event_inverse_phase_mask & (1 << m_Phase)) return false; CreatureEventAI_Event const& event = holder.Event; //Check event conditions based on the event type, also reset events switch (event.event_type) { case EVENT_T_TIMER: if (!me->isInCombat()) return false; //Repeat Timers holder.UpdateRepeatTimer(me, event.timer.repeatMin, event.timer.repeatMax); break; case EVENT_T_TIMER_OOC: if (me->isInCombat()) return false; //Repeat Timers holder.UpdateRepeatTimer(me, event.timer.repeatMin, event.timer.repeatMax); break; case EVENT_T_HP: { if (!me->isInCombat() || !me->GetMaxHealth()) return false; uint32 perc = uint32(me->GetHealthPct()); if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin) return false; //Repeat Timers holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax); break; } case EVENT_T_MANA: { if (!me->isInCombat() || !me->GetMaxPower(POWER_MANA)) return false; uint32 perc = (me->GetPower(POWER_MANA)*100) / me->GetMaxPower(POWER_MANA); if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin) return false; //Repeat Timers holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax); break; } case EVENT_T_AGGRO: break; case EVENT_T_KILL: //Repeat Timers holder.UpdateRepeatTimer(me, event.kill.repeatMin, event.kill.repeatMax); break; case EVENT_T_DEATH: case EVENT_T_EVADE: break; case EVENT_T_SPELLHIT: //Spell hit is special case, param1 and param2 handled within CreatureEventAI::SpellHit //Repeat Timers holder.UpdateRepeatTimer(me, event.spell_hit.repeatMin, event.spell_hit.repeatMax); break; case EVENT_T_RANGE: //Repeat Timers holder.UpdateRepeatTimer(me, event.range.repeatMin, event.range.repeatMax); break; case EVENT_T_OOC_LOS: //Repeat Timers holder.UpdateRepeatTimer(me, event.ooc_los.repeatMin, event.ooc_los.repeatMax); break; case EVENT_T_RESET: case EVENT_T_SPAWNED: break; case EVENT_T_TARGET_HP: { if (!me->isInCombat() || !me->getVictim() || !me->getVictim()->GetMaxHealth()) return false; uint32 perc = uint32(me->getVictim()->GetHealthPct()); if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin) return false; //Repeat Timers holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax); break; } case EVENT_T_TARGET_CASTING: if (!me->isInCombat() || !me->getVictim() || !me->getVictim()->IsNonMeleeSpellCasted(false, false, true)) return false; //Repeat Timers holder.UpdateRepeatTimer(me, event.target_casting.repeatMin, event.target_casting.repeatMax); break; case EVENT_T_FRIENDLY_HP: { if (!me->isInCombat()) return false; Unit* unit = DoSelectLowestHpFriendly((float)event.friendly_hp.radius, event.friendly_hp.hpDeficit); if (!unit) return false; actionInvoker = unit; //Repeat Timers holder.UpdateRepeatTimer(me, event.friendly_hp.repeatMin, event.friendly_hp.repeatMax); break; } case EVENT_T_FRIENDLY_IS_CC: { if (!me->isInCombat()) return false; std::list<Creature*> pList; DoFindFriendlyCC(pList, (float)event.friendly_is_cc.radius); //List is empty if (pList.empty()) return false; //We don't really care about the whole list, just return first available actionInvoker = *(pList.begin()); //Repeat Timers holder.UpdateRepeatTimer(me, event.friendly_is_cc.repeatMin, event.friendly_is_cc.repeatMax); break; } case EVENT_T_FRIENDLY_MISSING_BUFF: { std::list<Creature*> pList; DoFindFriendlyMissingBuff(pList, (float)event.friendly_buff.radius, event.friendly_buff.spellId); //List is empty if (pList.empty()) return false; //We don't really care about the whole list, just return first available actionInvoker = *(pList.begin()); //Repeat Timers holder.UpdateRepeatTimer(me, event.friendly_buff.repeatMin, event.friendly_buff.repeatMax); break; } case EVENT_T_SUMMONED_UNIT: { //Prevent event from occuring on no unit or non creatures if (!actionInvoker || actionInvoker->GetTypeId() != TYPEID_UNIT) return false; //Creature id doesn't match up if (actionInvoker->ToCreature()->GetEntry() != event.summon_unit.creatureId) return false; //Repeat Timers holder.UpdateRepeatTimer(me, event.summon_unit.repeatMin, event.summon_unit.repeatMax); break; } case EVENT_T_TARGET_MANA: { if (!me->isInCombat() || !me->getVictim() || !me->getVictim()->GetMaxPower(POWER_MANA)) return false; uint32 perc = (me->getVictim()->GetPower(POWER_MANA)*100) / me->getVictim()->GetMaxPower(POWER_MANA); if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin) return false; //Repeat Timers holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax); break; } case EVENT_T_REACHED_HOME: case EVENT_T_RECEIVE_EMOTE: break; case EVENT_T_BUFFED: { //Note: checked only aura for effect 0, if need check aura for effect 1/2 then // possible way: pack in event.buffed.amount 2 uint16 (ammount+effectIdx) Aura const* aura = me->GetAura(event.buffed.spellId); if (!aura || aura->GetStackAmount() < event.buffed.amount) return false; //Repeat Timers holder.UpdateRepeatTimer(me, event.buffed.repeatMin, event.buffed.repeatMax); break; } case EVENT_T_TARGET_BUFFED: { //Prevent event from occuring on no unit if (!actionInvoker) return false; //Note: checked only aura for effect 0, if need check aura for effect 1/2 then // possible way: pack in event.buffed.amount 2 uint16 (ammount+effectIdx) Aura const* aura = actionInvoker->GetAura(event.buffed.spellId); if (!aura || aura->GetStackAmount() < event.buffed.amount) return false; //Repeat Timers holder.UpdateRepeatTimer(me, event.buffed.repeatMin, event.buffed.repeatMax); break; } default: sLog->outErrorDb("CreatureEventAI: Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", me->GetEntry(), holder.Event.event_id, holder.Event.event_type); break; } //Disable non-repeatable events if (!(holder.Event.event_flags & EFLAG_REPEATABLE)) holder.Enabled = false; //Store random here so that all random actions match up uint32 rnd = rand(); //Return if chance for event is not met if (holder.Event.event_chance <= rnd % 100) return false; //Process actions for (uint8 j = 0; j < MAX_ACTIONS; ++j) ProcessAction(holder.Event.action[j], rnd, holder.Event.event_id, actionInvoker); return true; }
void UpdateAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (m_uiHealTimer < uiDiff) { if (Unit* pTarget = DoSelectLowestHpFriendly(50.0f)) { if (DoCastSpellIfCan(pTarget, SPELL_FLASH_HEAL) == CAST_OK) m_uiHealTimer = urand(15000, 20000); } } else m_uiHealTimer -= uiDiff; if (m_uiRenewTimer < uiDiff) { if (Unit* pTarget = DoSelectLowestHpFriendly(50.0f)) { if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_RENEW : SPELL_RENEW_H) == CAST_OK) m_uiRenewTimer = urand(5000, 10000); } } else m_uiRenewTimer -= uiDiff; if (m_uiShieldTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_SHIELD : SPELL_SHIELD_H) == CAST_OK) m_uiShieldTimer = urand(30000, 35000); } else m_uiShieldTimer -= uiDiff; if (m_uiDispelTimer < uiDiff) { Unit* pTarget = nullptr; CreatureList lTempList = DoFindFriendlyCC(50.0f); if (!lTempList.empty()) pTarget = *(lTempList.begin()); else pTarget = DoSelectLowestHpFriendly(50.0f); if (pTarget) { if (DoCastSpellIfCan(pTarget, SPELL_DISPEL_MAGIC) == CAST_OK) m_uiDispelTimer = urand(12000, 15000); } } else m_uiDispelTimer -= uiDiff; // Use the Medallion if CC - only on heroic. Not sure how many times they are allowed to use it. if (!m_bIsRegularMode && m_uiMedallionTimer) { if (m_creature->isFrozen() || m_creature->hasUnitState(UNIT_STAT_CAN_NOT_REACT)) { if (m_uiMedallionTimer <= uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_MEDALLION, CAST_TRIGGERED) == CAST_OK) m_uiMedallionTimer = 0; } else m_uiMedallionTimer -= uiDiff; } } if (m_uiSWPainTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, nullptr, SELECT_FLAG_PLAYER)) { if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_SHADOW_WORD_PAIN : SPELL_SHADOW_WORD_PAIN_H) == CAST_OK) m_uiSWPainTimer = 10000; } } else m_uiSWPainTimer -= uiDiff; if (m_uiScreamTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_SCREAM) == CAST_OK) m_uiScreamTimer = urand(15000, 20000); } else m_uiScreamTimer -= uiDiff; DoMeleeAttackIfReady(); }
bool UpdateCompanionAI(const uint32 uiDiff) { if (m_uiGoblinDragonGunTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_GOBLIN_DRAGON_GUN : SPELL_GOBLIN_DRAGON_GUN_H) == CAST_OK) m_uiGoblinDragonGunTimer = urand(10000, 20000); } else m_uiGoblinDragonGunTimer -= uiDiff; if (m_uiRocketLaunchTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, nullptr, SELECT_FLAG_PLAYER)) { if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_ROCKET_LAUNCH : SPELL_ROCKET_LAUNCH_H) == CAST_OK) m_uiRocketLaunchTimer = 9000; } } else m_uiRocketLaunchTimer -= uiDiff; if (m_uiFelIronBombTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, nullptr, SELECT_FLAG_PLAYER)) { if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_FEL_IRON_BOMB : SPELL_FEL_IRON_BOMB_H) == CAST_OK) m_uiFelIronBombTimer = 15000; } } else m_uiFelIronBombTimer -= uiDiff; if (m_uiRecombobulateTimer < uiDiff) { // Note: this should be casted only on Polyformed targets Unit* pTarget = nullptr; CreatureList lTempList = DoFindFriendlyCC(50.0f); if (!lTempList.empty()) pTarget = *(lTempList.begin()); else pTarget = DoSelectLowestHpFriendly(50.0f); if (pTarget) { if (DoCastSpellIfCan(pTarget, SPELL_RECOMBOBULATE) == CAST_OK) m_uiRecombobulateTimer = 2000; } } else m_uiRecombobulateTimer -= uiDiff; if (m_uiHighExplosiveSheepTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_HIGH_EXPLOSIVE_SHEEP) == CAST_OK) m_uiHighExplosiveSheepTimer = 65000; } else m_uiHighExplosiveSheepTimer -= uiDiff; return true; }
void UpdateAI(const uint32 diff) { DoMeleeAttackIfReady(); decrementTimers(); if (IAmDead()) return; if (me->GetPower(POWER_MANA) < 400 && isTimerReady(uiPotion_Timer)) { doCast(me, SPELL_MANA_POTION); uiPotion_Timer = 150; } if (me->GetPower(POWER_MANA)/me->GetMaxPower(POWER_MANA) < 10) { if (uiOom_Timer == 0) uiOom_Timer = 1; } BuffAndHealGroup(master); // Heal myself HealTarget (me, me->GetHealth() * 100 / me->GetMaxHealth()); //the rest are combat so return if not fighting opponent = SelectTarget(SELECT_TARGET_TOPAGGRO, 0); if (!opponent && !me->getVictim()) { DoNonCombatActions(); ResetOrGetNextTarget(); return; } //Cast totems. if (me->isInCombat() && isTimerReady(uiEarthTotem_Timer) && !master->HasAura(SPELL_STONE_SKIN_AURA, 0)) { doCast(me, SPELL_STONE_SKIN_TOTEM); GiveManaBack(); uiEarthTotem_Timer = 90; return; } if (me->isInCombat() && isTimerReady(uiFireTotem_Timer)) { doCast(me, SPELL_SEARING_TOTEM); GiveManaBack(); uiFireTotem_Timer = 180; return; } if (me->isInCombat() && isTimerReady(uiWindTotem_Timer)) { doCast(me, SPELL_WINDFURY_TOTEM); GiveManaBack(); uiWindTotem_Timer = 180; return; } if (me->isInCombat()) { switch(master->getClass()) { case CLASS_WARRIOR: case CLASS_DEATH_KNIGHT: case CLASS_ROGUE: if (isTimerReady(uiWaterTotem_Timer) && !master->HasAura(SPELL_HEALING_STREAM_AURA)) { doCast(me, SPELL_HEALING_STREAM_TOTEM); uiWaterTotem_Timer = 90; GiveManaBack(); return; } break; default: //everyone else gets a mana totem if (isTimerReady (uiWaterTotem_Timer) && !master->HasAura(SPELL_MANA_SPRING_AURA, 0)) { doCast(me, SPELL_MANA_SPRING_TOTEM); uiWaterTotem_Timer = 90; GiveManaBack(); return; } } } if (isTimerReady(uiFlameShock_Timer)) { doCast(opponent, SPELL_FLAME_SHOCK); uiFlameShock_Timer = 120; return; } if (isTimerReady(uiLightningBolt_Timer)) { doCast(opponent, SPELL_LIGHTNING_BOLT); uiLightningBolt_Timer = 180; return; } if (isTimerReady(uiEarthShock_Timer)) { doCast(opponent, SPELL_EARTH_SHOCK); uiEarthShock_Timer = 250; return; } //now try to heal bots and pets. DoSelectLowestHpFriendly will get //everyone in group including bots and pets. Unfortunately it can //not be triggered for % of lost HP, so we just set it to -1000. //This means low level players wont be healed because they wont have //enough HP. Unit* target = DoSelectLowestHpFriendly(40, 1000); if (target) { if (CanCast(target, GetSpellStore()->LookupEntry (SPELL_CHAIN_HEAL))) { doCast(target, SPELL_CHAIN_HEAL, false); uiOthersHeal_Timer = 50; } } else { target = DoSelectLowestHpFriendly(40, 500); //now try someone with less HP lost if (target) { if (CanCast(target, GetSpellStore()->LookupEntry (SPELL_CHAIN_HEAL))) { doCast(target, SPELL_CHAIN_HEAL, false); uiOthersHeal_Timer = 100; } } } ScriptedAI::UpdateAI(diff); }
void UpdateAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (m_bCanResurrect) { // When casting resuruction make sure to delay so on rez when reinstate battle deepsleep runs out if (m_uiWait_Timer < uiDiff) { // spell has script target on Mograine DoCastSpellIfCan(m_creature, SPELL_SCARLETRESURRECTION); DoScriptText(SAY_WH_RESSURECT, m_creature); m_bCanResurrect = false; } else m_uiWait_Timer -= uiDiff; } // Cast Deep sleep when health is less than 50% if (!m_bCanResurrectCheck && m_creature->GetHealthPercent() <= 50.0f) { DoCastSpellIfCan(m_creature, SPELL_DEEPSLEEP, CAST_INTERRUPT_PREVIOUS); m_bCanResurrectCheck = true; m_bCanResurrect = true; return; } // while in "resurrect-mode", don't do anything if (m_bCanResurrect) return; // If we are <75% hp cast healing spells at self or Mograine if (m_uiHeal_Timer < uiDiff) { if (Unit* pTarget = DoSelectLowestHpFriendly(50.0f)) { if (DoCastSpellIfCan(pTarget, SPELL_HEAL) == CAST_OK) m_uiHeal_Timer = 13000; } } else m_uiHeal_Timer -= uiDiff; // m_uiPowerWordShield_Timer if (m_uiPowerWordShield_Timer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_POWERWORDSHIELD) == CAST_OK) m_uiPowerWordShield_Timer = urand(22000, 45000); } else m_uiPowerWordShield_Timer -= uiDiff; // m_uiHolySmite_Timer if (m_uiHolySmite_Timer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_HOLYSMITE) == CAST_OK) m_uiHolySmite_Timer = urand(3500, 5000); } else m_uiHolySmite_Timer -= uiDiff; DoMeleeAttackIfReady(); }
void bot_ai::ResetOrGetNextTarget() { if (master->GetBotMustDie()) return; uint64 targetGUID = 0; // check if anyone has raid target //targetGUID = getTargetWithIcon(); Group *group = master->GetGroup(); targetGUID = group->GetTargetWithIconByGroup (m_creature->GetGUID()); if (targetGUID && targetGUID!=master->GetGUID()) { Unit * target = m_creature->GetCreature(*master, targetGUID); if (target && target->isAlive() && target->IsHostileTo(master) && target->isInCombat() /*&& m_creature->IsWithinDist(target, 30)*/) { BotAttackStart(target); return; } } AttackerSet m_attackers = master->getAttackers(); //check if anyone is attacking master if(gettingAttacked(m_attackers)) return; //check if anyone is attacking me m_attackers = m_creature->getAttackers(); if(gettingAttacked(m_attackers)) return; //check if master has a victim if(master->getVictim() && master->getVictim()->IsHostileTo(master)) { if(m_creature->IsWithinDist(m_creature->getVictim(), 50)) { BotAttackStart(master->getVictim()); return; } } //lastly check a random victim, including bots, pets, etc Unit *target = DoSelectLowestHpFriendly(30); if(target != NULL && target->isAlive() && !target->IsHostileToPlayers()) { m_attackers = target->getAttackers(); if(gettingAttacked(m_attackers)) { return; } } //if there is no one to attack, make sure we are following master if(m_creature->getVictim() == NULL && m_creature->GetCharmInfo()->GetCommandState() != COMMAND_STAY && master->GetDistance(m_creature) > 20 && !master->IsBeingTeleported()) { if (!master->isAlive()) master->SetBotCommandState(COMMAND_STAY); else if (master->GetBotCommandState()==COMMAND_ATTACK) master->SetBotCommandState(prevCommandState); return; } }
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 UpdateAI(uint32 diff) { npc_escortAI::UpdateAI(diff); if( !UpdateVictim() ) return; events.Update(diff); if( me->HasUnitState(UNIT_STATE_CASTING) ) return; switch( events.GetEvent() ) { case 0: break; case EVENT_MONK_SPELL_FLURRY_OF_BLOWS: me->CastSpell(me, SPELL_FLURRY_OF_BLOWS, false); events.RepeatEvent(urand(12000,18000)); break; case EVENT_MONK_SPELL_PUMMEL: if( me->GetVictim() ) me->CastSpell(me->GetVictim(), SPELL_PUMMEL, false); events.RepeatEvent(urand(8000,11000)); break; case EVENT_PRIESTESS_SPELL_HOLY_SMITE: if( me->GetVictim() ) me->CastSpell(me->GetVictim(), SPELL_HOLY_SMITE, false); events.RepeatEvent(urand(6000,8000)); break; case EVENT_PRIESTESS_SPELL_SHADOW_WORD_PAIN: if( me->GetVictim() ) me->CastSpell(me->GetVictim(), SPELL_SHADOW_WORD_PAIN, false); events.RepeatEvent(urand(12000,15000)); break; case EVENT_PRIESTESS_SPELL_FOUNTAIN_OF_LIGHT: me->CastSpell((Unit*)NULL, SPELL_FOUNTAIN_OF_LIGHT, false); events.RepeatEvent(urand(35000,45000)); break; case EVENT_PRIESTESS_SPELL_MIND_CONTROL_H: if( Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f, true) ) me->CastSpell(target, SPELL_MIND_CONTROL_H, false); events.RepeatEvent(urand(22000,30000)); break; case EVENT_LIGHTWIELDER_SPELL_BLAZING_LIGHT: { Unit* target = DoSelectLowestHpFriendly(40.0f); if( !target ) target = me; me->CastSpell(target, SPELL_BLAZING_LIGHT, false); events.RepeatEvent(urand(8000,12000)); } break; case EVENT_LIGHTWIELDER_SPELL_CLEAVE: if( me->GetVictim() ) me->CastSpell(me->GetVictim(), SPELL_CLEAVE, false); events.RepeatEvent(urand(6000,8000)); break; case EVENT_LIGHTWIELDER_SPELL_UNBALANCING_STRIKE_H: if( me->GetVictim() ) me->CastSpell(me->GetVictim(), SPELL_UNBALANCING_STRIKE_H, false); events.RepeatEvent(urand(12000,15000)); break; } DoMeleeAttackIfReady(); }