bool EffectScriptEffectCreature_spell_unstable_ooze(Unit* pCaster, uint32 uiSpellId, SpellEffectIndex uiEffIndex, Creature* pCreatureTarget, ObjectGuid /*originalCasterGuid*/) { if (uiSpellId == SPELL_UNSTABLE_OOZE && uiEffIndex == EFFECT_INDEX_2 && pCreatureTarget->GetEntry() == NPC_BIG_OOZE) { // send AI event on 5 stacks of unstable Ooze SpellAuraHolder* pOozeHolder = pCreatureTarget->GetSpellAuraHolder(uiSpellId); if (pOozeHolder) { // Note: stacks are increased after the effect is processed, so we need to use (stacks - 1) switch (pOozeHolder->GetStackAmount()) { case 1: DoScriptText(EMOTE_OOZE_GROW_1, pCreatureTarget); break; case 2: DoScriptText(EMOTE_OOZE_GROW_2, pCreatureTarget); break; case 4: pCreatureTarget->AI()->SendAIEvent(AI_EVENT_CUSTOM_A, pCaster, pCreatureTarget); // no break; case 3: DoScriptText(EMOTE_OOZE_GROW_3, pCreatureTarget); break; } } return true; } return false; }
void UpdateAI(const uint32 diff) override { if (!zealot) { if (Unit* owner = m_creature->GetCreator()) zealot = owner; } if (channelTarget == NULL/* || lastTarget == NULL */|| zealot == NULL) return; if (zealot->HasAura(SPELL_TWILIGHT_EVOLUTION) || zealot->isDead()) return; if (uiCheckPlayerIsBetween <= diff) { channelTarget = zealot; Map::PlayerList const &PlayerList = m_creature->GetMap()->GetPlayers(); if (!PlayerList.isEmpty()) { for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { if(i->getSource()->IsInBetween(m_creature, zealot, 1.0f)) channelTarget = i->getSource(); } } SpellAuraHolder* holder = channelTarget->GetSpellAuraHolder(SPELL_EVOLUTION, zealot->GetObjectGuid()); if (!holder) holder = channelTarget->_AddAura(SPELL_EVOLUTION, 15000, zealot); if (holder) { holder->ModStackAmount(1); holder->RefreshHolder(); if (holder->GetStackAmount() >= holder->GetSpellProto()->GetStackAmount()) { if(channelTarget == zealot) channelTarget->RemoveAllAuras(); zealot->CastSpell(channelTarget, SPELL_TWILIGHT_EVOLUTION, true); } } uiCheckPlayerIsBetween = 500; } else uiCheckPlayerIsBetween -= diff; if (uiNetherEssenceVisual <= diff) { m_creature->CastSpell(m_creature, SPELL_NETHERESSENCE_VISUAL, true); uiNetherEssenceVisual = urand(3500,4000); } else uiNetherEssenceVisual -= diff; }
void WorldSession::HandleCancelAuraOpcode(WorldPacket& recvPacket) { uint32 spellId; recvPacket >> spellId; SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId); if (!spellInfo) return; if (spellInfo->HasAttribute(SPELL_ATTR_CANT_CANCEL)) return; if (IsPassiveSpell(spellInfo)) return; if (!IsPositiveSpell(spellId)) { // ignore for remote control state if (!_player->IsSelfMover()) { // except own aura spells bool allow = false; for (int k = 0; k < MAX_EFFECT_INDEX; ++k) { SpellEffectEntry const* spellEffect = spellInfo->GetSpellEffect(SpellEffectIndex(k)); if (spellEffect && (spellEffect->EffectApplyAuraName == SPELL_AURA_MOD_POSSESS || spellEffect->EffectApplyAuraName == SPELL_AURA_MOD_POSSESS_PET)) { allow = true; break; } } // this also include case when aura not found if (!allow) return; } else return; } // channeled spell case (it currently casted then) if (IsChanneledSpell(spellInfo)) { if (Spell* curSpell = _player->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) if (curSpell->m_spellInfo->Id == spellId) _player->InterruptSpell(CURRENT_CHANNELED_SPELL); return; } SpellAuraHolder* holder = _player->GetSpellAuraHolder(spellId); // not own area auras can't be cancelled (note: maybe need to check for aura on holder and not general on spell) if (holder && holder->GetCasterGuid() != _player->GetObjectGuid() && HasAreaAuraEffect(holder->GetSpellProto())) return; // non channeled case _player->RemoveAurasDueToSpellByCancel(spellId); }
/** * GetDispelTarget() * return Unit* Returns unit to be dispelled. First checks 'critical' Healer(s), next Tank(s), next Master (if different from:), next DPS. * * return NULL If NULL is returned, no healing is required. At all. * * Will need extensive re-write for co-operation amongst multiple healers. As it stands, multiple healers would all pick the same 'ideal' * healing target. */ Player* PlayerbotClassAI::GetDispelTarget(DispelType dispelType, JOB_TYPE type, bool bMustBeOOC) { if (!m_ai) return nullptr; if (!m_bot) return nullptr; if (!m_bot->isAlive() || m_bot->IsInDuel()) return nullptr; if (bMustBeOOC && m_bot->isInCombat()) return nullptr; // First, fill the list of targets if (m_bot->GetGroup()) { // define seperately for sorting purposes - DO NOT CHANGE ORDER! std::vector<heal_priority> targets; Group::MemberSlotList const& groupSlot = m_bot->GetGroup()->GetMemberSlots(); for (Group::member_citerator itr = groupSlot.begin(); itr != groupSlot.end(); itr++) { Player *groupMember = sObjectMgr.GetPlayer(itr->guid); if (!groupMember || !groupMember->isAlive()) continue; JOB_TYPE job = GetTargetJob(groupMember); if (job & type) { uint32 dispelMask = GetDispellMask(dispelType); Unit::SpellAuraHolderMap const& auras = groupMember->GetSpellAuraHolderMap(); for (Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) { SpellAuraHolder *holder = itr->second; // Only return group members with negative magic effect if (dispelType == DISPEL_MAGIC && holder->IsPositive()) continue; // poison, disease and curse are always negative: return everyone if ((1 << holder->GetSpellProto()->Dispel) & dispelMask) targets.push_back( heal_priority(groupMember, 0, job) ); } } } // Sorts according to type: Healers first, tanks next, then master followed by DPS, thanks to the order of the TYPE enum std::sort(targets.begin(), targets.end()); if (targets.size()) return targets.at(0).p; } return nullptr; }
void Player::UpdateMasteryAuras() { if (!HasAuraType(SPELL_AURA_MASTERY)) { SetFloatValue(PLAYER_MASTERY, 0.0f); return; } float masteryValue = GetTotalAuraModifier(SPELL_AURA_MASTERY) + GetRatingBonusValue(CR_MASTERY); SetFloatValue(PLAYER_MASTERY, masteryValue); std::vector<uint32> const* masterySpells = GetTalentTreeMasterySpells(m_talentsPrimaryTree[m_activeSpec]); if (!masterySpells) return; for (uint32 i = 0; i < masterySpells->size(); ++i) { SpellAuraHolder* holder = GetSpellAuraHolder(masterySpells->at(i)); if (!holder) continue; SpellEntry const* spellEntry = holder->GetSpellProto(); // calculate mastery scaling coef int32 masteryCoef = GetMasteryCoefficient(spellEntry); if (!masteryCoef) continue; // update aura modifiers for (uint32 j = 0; j < MAX_EFFECT_INDEX; ++j) { Aura* aura = holder->GetAuraByEffectIndex(SpellEffectIndex(j)); if (!aura) continue; if (spellEntry->CalculateSimpleValue(SpellEffectIndex(j))) continue; aura->ApplyModifier(false, false); aura->GetModifier()->m_amount = int32(masteryValue * masteryCoef / 100.0f); aura->ApplyModifier(true, false); } } }
bool GOGossipSelect_go_ulduar_teleporter(Player *pPlayer, GameObject* pGo, uint32 sender, uint32 action) { int32 damage = 0; if(sender != GOSSIP_SENDER_MAIN) return false; if(!pPlayer->getAttackers().empty()) return false; if(action >= 0 && action <= PORTALS_COUNT) pPlayer->TeleportTo(PortalLoc[action].map_num, PortalLoc[action].x, PortalLoc[action].y, PortalLoc[action].z, PortalLoc[action].o); if (PortalLoc[action].spellID != 0 ) if (SpellEntry const* spell = (SpellEntry *)GetSpellStore()->LookupEntry(PortalLoc[action].spellID)) { SpellAuraHolder *holder = CreateSpellAuraHolder(spell, pPlayer, pPlayer); Aura *aura = CreateAura(spell, EFFECT_INDEX_2, NULL, holder, pPlayer); holder->AddAura(aura, EFFECT_INDEX_2); } pPlayer->CLOSE_GOSSIP_MENU(); return true; }
void DynamicObject::Delay(int32 delaytime) { m_aliveDuration -= delaytime; for(AffectedSet::iterator iter = m_affected.begin(); iter != m_affected.end(); ) { Unit *target = GetMap()->GetUnit((*iter)); if (target) { SpellAuraHolder *holder = target->GetSpellAuraHolder(m_spellId, GetCasterGuid().GetRawValue()); if (!holder) { ++iter; continue; } bool foundAura = false; for (int32 i = m_effIndex + 1; i < MAX_EFFECT_INDEX; ++i) { SpellEffectEntry const* effect = holder->GetSpellProto()->GetSpellEffect(SpellEffectIndex(i)); if(!effect) continue; if ((effect->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA || effect->Effect == SPELL_EFFECT_ADD_FARSIGHT) && holder->m_auras[i]) { foundAura = true; break; } } if (foundAura) { ++iter; continue; } target->DelaySpellAuraHolder(m_spellId, delaytime, GetCasterGuid().GetRawValue()); ++iter; } else m_affected.erase(iter++); } }
bool PlayerbotPriestAI::HealTarget(Unit* target) { PlayerbotAI* ai = GetAI(); uint8 hp = target->GetHealth() * 100 / target->GetMaxHealth(); if (CURE_DISEASE > 0 && ai->GetCombatOrder() != PlayerbotAI::ORDERS_NODISPEL) { uint32 dispelMask = GetDispellMask(DISPEL_DISEASE); Unit::SpellAuraHolderMap const& auras = target->GetSpellAuraHolderMap(); for(Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) { SpellAuraHolder *holder = itr->second; if ((1<<holder->GetSpellProto()->Dispel) & dispelMask) { if(holder->GetSpellProto()->Dispel == DISPEL_DISEASE) ai->CastSpell(CURE_DISEASE, *target); return false; } } } if (hp >= 80) return false; if (hp < 25 && FLASH_HEAL && ai->CastSpell(FLASH_HEAL, *target)) return true; else if (hp < 30 && GREATER_HEAL > 0 && ai->CastSpell(GREATER_HEAL, *target)) return true; else if (hp < 33 && BINDING_HEAL > 0 && ai->CastSpell(BINDING_HEAL, *target)) return true; else if (hp < 40 && PRAYER_OF_HEALING > 0 && ai->CastSpell(PRAYER_OF_HEALING, *target)) return true; else if (hp < 50 && CIRCLE_OF_HEALING > 0 && ai->CastSpell(CIRCLE_OF_HEALING, *target)) return true; else if (hp < 60 && HEAL > 0 && ai->CastSpell(HEAL, *target)) return true; else if (hp < 80 && RENEW > 0 && !target->HasAura(RENEW) && ai->CastSpell(RENEW, *target)) return true; else return false; } // end HealTarget
bool EffectAuraDummy_spell_aura_dummy_living_flare(const Aura* pAura, bool bApply) { if (pAura->GetId() == SPELL_LIVING_FLARE_MASTER && pAura->GetEffIndex() == EFFECT_INDEX_0 && bApply) { if (Creature* pTarget = (Creature*)pAura->GetTarget()) { pTarget->CastSpell(pTarget, SPELL_FEL_FLAREUP, TRIGGERED_OLD_TRIGGERED); SpellAuraHolder* pHolder = pTarget->GetSpellAuraHolder(SPELL_FEL_FLAREUP); if (pHolder) { if (pHolder->GetStackAmount() >= MAX_FLAREUP_STACKS) pTarget->AI()->SendAIEvent(AI_EVENT_CUSTOM_A, pTarget, pTarget); // Note: cosmetic aura is removed, so we need to add it back. This needs to be fixed else pTarget->CastSpell(pTarget, SPELL_LIVING_COSMETIC, TRIGGERED_OLD_TRIGGERED); } } } return true; }
void UpdateAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; // Unstable Ooze if (m_uiUnstableExplosionCheckTimer) { if (m_uiUnstableExplosionCheckTimer <= uiDiff) { m_uiUnstableExplosionCheckTimer = 1000; SpellAuraHolder* holder = m_creature->GetSpellAuraHolder(SPELL_UNSTABLE_OOZE); if (holder && holder->GetStackAmount() >= 5) { if (DoCastSpellIfCan(m_creature, SPELL_UNSTABLE_EXPLOSION) == CAST_OK) { if (m_pInstance) { if (Creature* pRotface = m_pInstance->GetSingleCreatureFromStorage(NPC_ROTFACE)) DoScriptText(SAY_OOZE_EXPLODE, pRotface); } } } } else m_uiUnstableExplosionCheckTimer -= uiDiff; } // Sticky Ooze if (m_uiStickyOozeTimer <= uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_STICKY_OOZE) == CAST_OK) m_uiStickyOozeTimer = urand(10000, 15000); } else m_uiStickyOozeTimer -= uiDiff; DoMeleeAttackIfReady(); }
bool BSWScriptedAI::_doAura(uint8 m_uiSpellIdx, Unit* pTarget, SpellEffectIndex index) { SpellTable* pSpell = &m_BossSpell[m_uiSpellIdx]; if (!pTarget || !pTarget->IsInMap(m_creature) || !pTarget->isAlive()) { error_log("BSW: FAILED adding aura of spell number %u - no target or target not in map or target is dead",pSpell->m_uiSpellEntry[currentDifficulty]); return false; } if (_hasAura(m_uiSpellIdx,pTarget)) debug_log("BSW: adding aura stack from spell %u index %u",pSpell->m_uiSpellEntry[currentDifficulty], index); else debug_log("BSW: adding new aura from spell %u index %u",pSpell->m_uiSpellEntry[currentDifficulty], index); SpellEntry const *spell = (SpellEntry *)GetSpellStore()->LookupEntry(pSpell->m_uiSpellEntry[currentDifficulty]); if (spell && spell->Effect[index] < TOTAL_SPELL_EFFECTS) { if (IsSpellAppliesAura(spell, (1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) || IsSpellHaveEffect(spell, SPELL_EFFECT_PERSISTENT_AREA_AURA)) { SpellAuraHolder *holder = CreateSpellAuraHolder(spell, pTarget, pTarget); int32 basepoint = pSpell->varData ? pSpell->varData - 1 : spell->EffectBasePoints[index] + 1; if ( IsAreaAuraEffect(spell->Effect[index]) || spell->Effect[index] == SPELL_EFFECT_APPLY_AURA || spell->Effect[index] == SPELL_EFFECT_PERSISTENT_AREA_AURA ) { Aura *aura = CreateAura(spell, SpellEffectIndex(index), &basepoint, holder, pTarget); holder->AddAura(aura, SpellEffectIndex(index)); return true; } } } error_log("BSW: FAILED adding aura from spell %u index %u",pSpell->m_uiSpellEntry[currentDifficulty], index); return false; };
CombatManeuverReturns PlayerbotWarriorAI::DoNextCombatManeuverPVE(Unit* pTarget) { if (!m_ai) return RETURN_NO_ACTION_ERROR; if (!m_bot) return RETURN_NO_ACTION_ERROR; //float fTargetDist = m_bot->GetCombatDistance(pTarget, true); //Used to determine if this bot is highest on threat Unit* newTarget = m_ai->FindAttacker((PlayerbotAI::ATTACKERINFOTYPE)(PlayerbotAI::AIT_VICTIMSELF | PlayerbotAI::AIT_HIGHESTTHREAT), m_bot); Unit* pVictim = pTarget->getVictim(); // do shouts, berserker rage, etc... if (BERSERKER_RAGE > 0 && !m_bot->HasAura(BERSERKER_RAGE, EFFECT_INDEX_0)) m_ai->CastSpell(BERSERKER_RAGE); else if (BLOODRAGE > 0 && m_ai->GetRageAmount() <= 10) m_ai->CastSpell(BLOODRAGE); Creature* pCreature = (Creature*) pTarget; // Prevent low health humanoid from fleeing with Hamstring if ((m_bot->HasAura(BATTLE_STANCE, EFFECT_INDEX_0) || m_bot->HasAura(BERSERKER_STANCE, EFFECT_INDEX_0)) && pTarget->GetHealthPercent() < 20 && !m_ai->IsElite(pTarget, true)) { if (HAMSTRING > 0 && !pTarget->HasAura(HAMSTRING, EFFECT_INDEX_0) && m_ai->CastSpell(HAMSTRING, *pTarget)) return RETURN_CONTINUE; } CheckShouts(); // Get bot spec. If bot has tank orders, force spec to protection uint32 spec = ((m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_TANK) ? WARRIOR_SPEC_PROTECTION : m_bot->GetSpec()); if (spec == WARRIOR_SPEC_FURY && (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_ASSIST)) { // Try to interrupt spell if target is casting one if (pTarget->IsNonMeleeSpellCasted(true)) { if (PUMMEL > 0 && m_bot->IsSpellReady(PUMMEL) && m_ai->CastSpell(PUMMEL, *pTarget)) return RETURN_CONTINUE; } if (DEATH_WISH > 0 && !m_bot->HasAura(DEATH_WISH, EFFECT_INDEX_0) && m_bot->IsSpellReady(DEATH_WISH) && m_ai->CastSpell(DEATH_WISH, *m_bot)) return RETURN_CONTINUE; if (EXECUTE > 0 && pTarget->GetHealthPercent() < 20 && m_ai->CastSpell(EXECUTE, *pTarget)) return RETURN_CONTINUE; if (BLOODTHIRST > 0 && m_bot->IsSpellReady(BLOODTHIRST) && m_ai->CastSpell(BLOODTHIRST, *pTarget)) return RETURN_CONTINUE; if (WHIRLWIND > 0 && m_bot->IsSpellReady(WHIRLWIND) && m_ai->CastSpell(WHIRLWIND, *pTarget)) return RETURN_CONTINUE; if (HEROIC_STRIKE > 0 && m_ai->CastSpell(HEROIC_STRIKE, *pTarget)) return RETURN_CONTINUE; } else if (spec == WARRIOR_SPEC_ARMS || (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_ASSIST)) { // Try to interrupt spell if target is casting one if (pTarget->IsNonMeleeSpellCasted(true)) { if (SHIELD_BASH > 0 && m_ai->CastSpell(SHIELD_BASH, *pTarget)) return RETURN_CONTINUE; } // If bot's target is also attacking the bot, use retaliation for extra attacks if (RETALIATION > 0 && pVictim == m_bot && m_ai->GetAttackerCount() >= 2 && m_bot->IsSpellReady(RETALIATION) && !m_bot->HasAura(RETALIATION, EFFECT_INDEX_0) && m_ai->CastSpell(RETALIATION, *m_bot)) return RETURN_CONTINUE; if (EXECUTE > 0 && pTarget->GetHealthPercent() < 20 && m_ai->CastSpell(EXECUTE, *pTarget)) return RETURN_CONTINUE; if (REND > 0 && !pTarget->HasAura(REND, EFFECT_INDEX_0) && m_ai->CastSpell(REND, *pTarget)) return RETURN_CONTINUE; if (MORTAL_STRIKE > 0 && m_bot->IsSpellReady(MORTAL_STRIKE) && m_ai->CastSpell(MORTAL_STRIKE, *pTarget)) return RETURN_CONTINUE; if (OVERPOWER > 0 && m_bot->IsSpellReady(OVERPOWER)) { uint8 base = pTarget->RollMeleeOutcomeAgainst(m_bot, BASE_ATTACK, SPELL_SCHOOL_MASK_NORMAL); uint8 off = pTarget->RollMeleeOutcomeAgainst(m_bot, OFF_ATTACK, SPELL_SCHOOL_MASK_NORMAL); if (base == MELEE_HIT_DODGE || off == MELEE_HIT_DODGE) { if (m_bot->IsSpellReady(OVERPOWER) && m_ai->CastSpell(OVERPOWER, *pTarget)) return RETURN_CONTINUE; } } if (THUNDER_CLAP > 0 && !pTarget->HasAura(THUNDER_CLAP) && m_ai->CastSpell(THUNDER_CLAP, *pTarget)) return RETURN_CONTINUE; if (HEROIC_STRIKE > 0 && m_ai->CastSpell(HEROIC_STRIKE, *pTarget)) return RETURN_CONTINUE; if (SLAM > 0 && m_ai->CastSpell(SLAM, *pTarget)) return RETURN_CONTINUE; } else if (spec == WARRIOR_SPEC_PROTECTION) { // First check: is bot's target targeting bot? if (!newTarget) { // Cast taunt on bot current target if the mob is targeting someone else if (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_TANK && TAUNT > 0 && m_bot->IsSpellReady(TAUNT) && m_ai->CastSpell(TAUNT, *pTarget)) return RETURN_CONTINUE; } // If tank is on the verge of dying but "I DON'T WANT TO DIE !!! :'-((" // TODO: should behaviour (or treshold) be different between elite and normal mobs? We don't want bots to burn such precious cooldown needlessly if (m_bot->GetHealthPercent() < 10) { // Cast Last Stand first because it has lower cooldown if (LAST_STAND > 0 && !m_bot->HasAura(LAST_STAND, EFFECT_INDEX_0) && m_ai->CastSpell(LAST_STAND, *m_bot)) { m_ai->TellMaster("I'm using LAST STAND"); return RETURN_CONTINUE; } // Cast Shield Wall only if Last Stand is on cooldown and not active if (SHIELD_WALL > 0 && (!m_bot->IsSpellReady(LAST_STAND) || LAST_STAND == 0) && !m_bot->HasAura(LAST_STAND, EFFECT_INDEX_0) && !m_bot->HasAura(SHIELD_WALL, EFFECT_INDEX_0) && m_ai->CastSpell(SHIELD_WALL, *m_bot)) { m_ai->TellMaster("I'm using SHIELD WALL"); return RETURN_CONTINUE; } } // Try to interrupt spell if target is casting one and target is not a worldboss (they are almost all immune to interrupt) if (pTarget->IsNonMeleeSpellCasted(true) && !m_ai->IsElite(pTarget, true)) { if (SHIELD_BASH > 0 && m_ai->CastSpell(SHIELD_BASH, *pTarget)) return RETURN_CONTINUE; } //Do not waste rage applying Sunder Armor if it is already stacked 5 times if (SUNDER_ARMOR > 0) { if (!pTarget->HasAura(SUNDER_ARMOR) && m_ai->CastSpell(SUNDER_ARMOR, *pTarget)) // no stacks: cast it return RETURN_CONTINUE; else { SpellAuraHolder* holder = pTarget->GetSpellAuraHolder(SUNDER_ARMOR); if (holder && (holder->GetStackAmount() < 5) && m_ai->CastSpell(SUNDER_ARMOR, *pTarget)) return RETURN_CONTINUE; } } if (REVENGE > 0 && m_bot->IsSpellReady(REVENGE)) { uint8 base = pTarget->RollMeleeOutcomeAgainst(m_bot, BASE_ATTACK, SPELL_SCHOOL_MASK_NORMAL); uint8 off = pTarget->RollMeleeOutcomeAgainst(m_bot, OFF_ATTACK, SPELL_SCHOOL_MASK_NORMAL); if (base == MELEE_HIT_PARRY || base == MELEE_HIT_DODGE || base == MELEE_HIT_BLOCK || off == MELEE_HIT_PARRY || off == MELEE_HIT_DODGE || off == MELEE_HIT_BLOCK) if (m_ai->CastSpell(REVENGE, *pTarget)) return RETURN_CONTINUE; } if (REND > 0 && !pTarget->HasAura(REND, EFFECT_INDEX_0) && m_ai->CastSpell(REND, *pTarget)) return RETURN_CONTINUE; if (DEMORALIZING_SHOUT > 0 && !pTarget->HasAura(DEMORALIZING_SHOUT, EFFECT_INDEX_0) && m_ai->CastSpell(DEMORALIZING_SHOUT, *pTarget)) return RETURN_CONTINUE; // check that target is dangerous (elite) before casting shield block: preserve bot cooldowns if (SHIELD_BLOCK > 0 && m_ai->IsElite(pTarget) && !m_bot->HasAura(SHIELD_BLOCK, EFFECT_INDEX_0) && m_ai->CastSpell(SHIELD_BLOCK, *m_bot)) return RETURN_CONTINUE; // TODO: only cast disarm if target has equipment? if (DISARM > 0 && !pTarget->HasAura(DISARM, EFFECT_INDEX_0) && m_ai->CastSpell(DISARM, *pTarget)) return RETURN_CONTINUE; if (CONCUSSION_BLOW > 0 && m_bot->IsSpellReady(CONCUSSION_BLOW) && m_ai->CastSpell(CONCUSSION_BLOW, *pTarget)) return RETURN_CONTINUE; if (SHIELD_SLAM > 0 && m_bot->IsSpellReady(SHIELD_SLAM) && m_ai->CastSpell(SHIELD_SLAM, *pTarget)) return RETURN_CONTINUE; if (HEROIC_STRIKE > 0 && m_ai->CastSpell(HEROIC_STRIKE, *pTarget)) return RETURN_CONTINUE; } /* case WarriorBattle: if (SWEEPING_STRIKES > 0 && m_ai->GetAttackerCount() >= 2 && !m_bot->HasAura(SWEEPING_STRIKES, EFFECT_INDEX_0) && m_ai->CastSpell(SWEEPING_STRIKES, *m_bot)) return RETURN_CONTINUE; if (INTIMIDATING_SHOUT > 0 && m_ai->GetAttackerCount() > 5 && m_ai->CastSpell(INTIMIDATING_SHOUT, *pTarget)) return RETURN_CONTINUE; if (CHALLENGING_SHOUT > 0 && pVictim != m_bot && m_ai->GetHealthPercent() > 25 && !pTarget->HasAura(MOCKING_BLOW, EFFECT_INDEX_0) && !pTarget->HasAura(CHALLENGING_SHOUT, EFFECT_INDEX_0) && m_ai->CastSpell(CHALLENGING_SHOUT, *pTarget)) return RETURN_CONTINUE; if (CLEAVE > 0 && m_ai->CastSpell(CLEAVE, *pTarget)) return RETURN_CONTINUE; if (PIERCING_HOWL > 0 && && m_ai->GetAttackerCount() >= 3 && !pTarget->HasAura(WAR_STOMP, EFFECT_INDEX_0) && !pTarget->HasAura(PIERCING_HOWL, EFFECT_INDEX_0) && !pTarget->HasAura(SHOCKWAVE, EFFECT_INDEX_0) && !pTarget->HasAura(CONCUSSION_BLOW, EFFECT_INDEX_0) && m_ai->CastSpell(PIERCING_HOWL, *pTarget)) return RETURN_CONTINUE; if (MOCKING_BLOW > 0 && pVictim != m_bot && m_ai->GetHealthPercent() > 25 && !pTarget->HasAura(MOCKING_BLOW, EFFECT_INDEX_0) && !pTarget->HasAura(CHALLENGING_SHOUT, EFFECT_INDEX_0) && m_ai->CastSpell(MOCKING_BLOW, *pTarget)) return RETURN_CONTINUE; if (m_bot->getRace() == RACE_TAUREN && !pTarget->HasAura(WAR_STOMP, EFFECT_INDEX_0) && !pTarget->HasAura(PIERCING_HOWL, EFFECT_INDEX_0) && !pTarget->HasAura(CONCUSSION_BLOW, EFFECT_INDEX_0) && m_ai->CastSpell(WAR_STOMP, *pTarget)) return RETURN_CONTINUE; if (m_bot->getRace() == RACE_HUMAN && m_bot->hasUnitState(UNIT_STAT_STUNNED) || m_bot->HasAuraType(SPELL_AURA_MOD_FEAR) || m_bot->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED) || m_bot->HasAuraType(SPELL_AURA_MOD_CHARM) && m_ai->CastSpell(EVERY_MAN_FOR_HIMSELF, *m_bot)) return RETURN_CONTINUE; if (m_bot->getRace() == RACE_UNDEAD && m_bot->HasAuraType(SPELL_AURA_MOD_FEAR) || m_bot->HasAuraType(SPELL_AURA_MOD_CHARM) && m_ai->CastSpell(WILL_OF_THE_FORSAKEN, *m_bot)) return RETURN_CONTINUE; if (m_bot->getRace() == RACE_DWARF && m_bot->HasAuraState(AURA_STATE_DEADLY_POISON) && m_ai->CastSpell(STONEFORM, *m_bot)) return RETURN_CONTINUE; if (m_bot->getRace() == RACE_GNOME && m_bot->hasUnitState(UNIT_STAT_STUNNED) || m_bot->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED) && m_ai->CastSpell(ESCAPE_ARTIST, *m_bot)) return RETURN_CONTINUE; if (m_bot->getRace() == RACE_ORC && !m_bot->HasAura(BLOOD_FURY, EFFECT_INDEX_0) && m_ai->CastSpell(BLOOD_FURY, *m_bot)) return RETURN_CONTINUE; if (m_bot->getRace() == RACE_TROLL && !m_bot->HasAura(BERSERKING, EFFECT_INDEX_0) && m_ai->CastSpell(BERSERKING, *m_bot)) return RETURN_CONTINUE; break;*/ return RETURN_NO_ACTION_OK; }
CombatManeuverReturns PlayerbotShamanAI::HealPlayer(Player* target) { CombatManeuverReturns r = PlayerbotClassAI::HealPlayer(target); if (r != RETURN_NO_ACTION_OK) return r; if (!target->isAlive()) { if (ANCESTRAL_SPIRIT && m_ai->CastSpell(ANCESTRAL_SPIRIT, *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 } // Dispel if necessary if ((CURE_DISEASE_SHAMAN > 0 || CURE_POISON_SHAMAN > 0) && (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_NODISPEL) == 0) { uint32 dispelMask = GetDispellMask(DISPEL_POISON); uint32 dispelMask2 = GetDispellMask(DISPEL_DISEASE); Unit::SpellAuraHolderMap const& auras = target->GetSpellAuraHolderMap(); for (Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) { SpellAuraHolder *holder = itr->second; if ((1 << holder->GetSpellProto()->Dispel) & dispelMask) { if (holder->GetSpellProto()->Dispel == DISPEL_POISON) { if (m_ai->CastSpell(CURE_POISON_SHAMAN, *target)) return RETURN_CONTINUE; return RETURN_NO_ACTION_ERROR; } } else if ((1 << holder->GetSpellProto()->Dispel) & dispelMask2) { if (holder->GetSpellProto()->Dispel == DISPEL_DISEASE) { if (m_ai->CastSpell(CURE_DISEASE_SHAMAN, *target)) return RETURN_CONTINUE; return RETURN_NO_ACTION_ERROR; } } } } // Everyone is healthy enough, return OK. MUST correlate to highest value below (should be last HP check) if (target->GetHealthPercent() >= 80) return RETURN_NO_ACTION_OK; // Technically the best rotation is CHAIN + LHW + LHW subbing in HW for trouble (bad mana efficiency) if (target->GetHealthPercent() < 30 && HEALING_WAVE > 0 && m_ai->CastSpell(HEALING_WAVE, *target)) return RETURN_CONTINUE; if (target->GetHealthPercent() < 50 && LESSER_HEALING_WAVE > 0 && m_ai->CastSpell(LESSER_HEALING_WAVE, *target)) return RETURN_CONTINUE; if (target->GetHealthPercent() < 80 && CHAIN_HEAL > 0 && m_ai->CastSpell(CHAIN_HEAL, *target)) return RETURN_CONTINUE; return RETURN_NO_ACTION_UNKNOWN; } // end HealTarget
CombatManeuverReturns PlayerbotPriestAI::HealPlayer(Player* target) { CombatManeuverReturns r = PlayerbotClassAI::HealPlayer(target); if (r != RETURN_NO_ACTION_OK) return r; if (!target->isAlive()) { if (RESURRECTION && m_ai->CastSpell(RESURRECTION, *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 (CURE_DISEASE > 0 && (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_NODISPEL) == 0) { uint32 dispelMask = GetDispellMask(DISPEL_DISEASE); Unit::SpellAuraHolderMap const& auras = target->GetSpellAuraHolderMap(); for (Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) { SpellAuraHolder *holder = itr->second; if ((1 << holder->GetSpellProto()->Dispel) & dispelMask) { if (holder->GetSpellProto()->Dispel == DISPEL_DISEASE) { m_ai->CastSpell(CURE_DISEASE, *target); return RETURN_CONTINUE; } } } } uint8 hp = target->GetHealthPercent(); uint8 hpSelf = m_ai->GetHealthPercent(); if (hp >= 90) return RETURN_NO_ACTION_OK; // TODO: Integrate shield here if (hp < 35 && FLASH_HEAL > 0 && m_ai->CastSpell(FLASH_HEAL, *target)) return RETURN_CONTINUE; if (hp < 45 && GREATER_HEAL > 0 && m_ai->CastSpell(GREATER_HEAL, *target)) return RETURN_CONTINUE; // Heals target AND self for equal amount if (hp < 60 && hpSelf < 80 && BINDING_HEAL > 0 && m_ai->CastSpell(BINDING_HEAL, *target)) return RETURN_CONTINUE; if (hp < 60 && PRAYER_OF_MENDING > 0 && !target->HasAura(PRAYER_OF_MENDING, EFFECT_INDEX_0) && CastSpell(PRAYER_OF_MENDING, target)) return RETURN_FINISHED_FIRST_MOVES; if (hp < 60 && HEAL > 0 && m_ai->CastSpell(HEAL, *target)) return RETURN_CONTINUE; if (hp < 90 && RENEW > 0 && !target->HasAura(RENEW) && m_ai->CastSpell(RENEW, *target)) return RETURN_CONTINUE; // Group heal. Not really useful until a group check is available? //if (hp < 40 && PRAYER_OF_HEALING > 0 && m_ai->CastSpell(PRAYER_OF_HEALING, *target) & RETURN_CONTINUE) // return RETURN_CONTINUE; // Group heal. Not really useful until a group check is available? //if (hp < 50 && CIRCLE_OF_HEALING > 0 && m_ai->CastSpell(CIRCLE_OF_HEALING, *target) & RETURN_CONTINUE) // return RETURN_CONTINUE; return RETURN_NO_ACTION_OK; } // 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) { 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)) 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 && ai->In_Reach(target,REJUVENATION) && !target->HasAura(REJUVENATION) && ai->CastSpell(REJUVENATION, *target)) return true; if (hp < 60 && LIFEBLOOM > 0 && ai->In_Reach(target,LIFEBLOOM) && !target->HasAura(LIFEBLOOM) && ai->CastSpell(LIFEBLOOM, *target)) return true; if (hp < 55 && REGROWTH > 0 && ai->In_Reach(target,REGROWTH) && !target->HasAura(REGROWTH) && ai->CastSpell(REGROWTH, *target)) return true; if (hp < 50 && SWIFTMEND > 0 && ai->In_Reach(target,SWIFTMEND) && (target->HasAura(REJUVENATION) || target->HasAura(REGROWTH)) && ai->CastSpell(SWIFTMEND, *target)) return true; if (hp < 45 && WILD_GROWTH > 0 && ai->In_Reach(target,WILD_GROWTH) && !target->HasAura(WILD_GROWTH) && ai->CastSpell(WILD_GROWTH, *target)) return true; if (hp < 30 && NOURISH > 0 && ai->In_Reach(target,NOURISH) && ai->CastSpell(NOURISH, *target)) return true; if (hp < 25 && HEALING_TOUCH > 0 && ai->In_Reach(target,HEALING_TOUCH) && ai->CastSpell(HEALING_TOUCH, *target)) return true; return false; } // end HealTarget
bool BSWScriptedAI::_doAura(uint32 SpellID, Unit* pTarget, SpellEffectIndex index, int32 basepoint, bool isStack) { if (!pTarget || !pTarget->IsInMap(m_creature) || !pTarget->isAlive()) { error_log("BSW: FAILED adding aura of spell number %u - no target or target not in map or target is dead",SpellID); return false; } if (_hasAura(SpellID,pTarget)) debug_log("BSW: adding aura stack from spell %u index %u",SpellID, index); else debug_log("BSW: adding new aura from spell %u index %u",SpellID, index); SpellEntry const *spell = (SpellEntry *)GetSpellStore()->LookupEntry(SpellID); if (spell) { if (IsSpellAppliesAura(spell, (1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) || IsSpellHaveEffect(spell, SPELL_EFFECT_PERSISTENT_AREA_AURA)) { int32 _basepoint = basepoint ? basepoint - 1 : spell->EffectBasePoints[index] + 1; bool addedToExisting = true; SpellAuraHolder* holder = pTarget->GetSpellAuraHolder(SpellID, pTarget->GetGUID()); Aura* aura = NULL; if (!holder) { holder = CreateSpellAuraHolder(spell, pTarget, pTarget); addedToExisting = false; } if (aura = holder->GetAuraByEffectIndex(index)) { if (isStack) holder->ModStackAmount(1); } else { aura = CreateAura(spell, index, &_basepoint, holder, pTarget); aura->SetAuraDuration(aura->GetAuraMaxDuration()); holder->AddAura(aura, index); } if (addedToExisting) { pTarget->AddAuraToModList(aura); holder->SetInUse(true); aura->ApplyModifier(true,true); holder->SetInUse(false); } else pTarget->AddSpellAuraHolder(holder); return true; } } error_log("BSW: FAILED adding aura from spell %u index %u",SpellID, index); return false; };
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 PlayerbotMageAI::DoNextCombatManeuverPVE(Unit *pTarget) { if (!m_ai) return RETURN_NO_ACTION_ERROR; if (!m_bot) return RETURN_NO_ACTION_ERROR; Unit* pVictim = pTarget->getVictim(); bool meleeReach = m_bot->CanReachWithMeleeAttack(pTarget); uint32 spec = m_bot->GetSpec(); if (m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_RANGED && !meleeReach) m_ai->SetCombatStyle(PlayerbotAI::COMBAT_RANGED); // switch to melee if in melee range AND can't shoot OR have no ranged (wand) equipped else if(m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_MELEE && meleeReach && (SHOOT == 0 || !m_bot->GetWeaponForAttack(RANGED_ATTACK, true, true))) m_ai->SetCombatStyle(PlayerbotAI::COMBAT_MELEE); //Used to determine if this bot is highest on threat Unit *newTarget = m_ai->FindAttacker((PlayerbotAI::ATTACKERINFOTYPE) (PlayerbotAI::AIT_VICTIMSELF | PlayerbotAI::AIT_HIGHESTTHREAT), m_bot); // Remove curse on group members if (Player* pCursedTarget = GetDispelTarget(DISPEL_CURSE)) { if (MAGE_REMOVE_CURSE > 0 && CastSpell(MAGE_REMOVE_CURSE, pCursedTarget)) return RETURN_CONTINUE; } if (newTarget && !m_ai->IsNeutralized(newTarget)) // Bot has aggro and the mob is not already crowd controled { if (newTarget->GetHealthPercent() > 25) { // If elite if (m_ai->IsElite(newTarget)) { // If the attacker is a beast or humanoid, let's the bot give it a form more suited to the low intellect of something fool enough to attack a mage Creature * pCreature = (Creature*) newTarget; if (pCreature && (pCreature->GetCreatureInfo()->CreatureType == CREATURE_TYPE_HUMANOID || pCreature->GetCreatureInfo()->CreatureType == CREATURE_TYPE_BEAST)) { if (POLYMORPH > 0 && CastSpell(POLYMORPH, newTarget)) return RETURN_CONTINUE; } // Things are getting dire: cast Ice block if (ICE_BLOCK > 0 && !m_bot->HasSpellCooldown(ICE_BLOCK) && m_ai->GetHealthPercent() < 30 && !m_bot->HasAura(ICE_BLOCK, EFFECT_INDEX_0) && m_ai->CastSpell(ICE_BLOCK)) return RETURN_CONTINUE; // Cast Ice Barrier if health starts to goes low if (ICE_BARRIER > 0 && !m_bot->HasSpellCooldown(ICE_BARRIER) && m_ai->GetHealthPercent() < 50 && !m_bot->HasAura(ICE_BARRIER) && m_ai->SelfBuff(ICE_BARRIER)) return RETURN_CONTINUE; // Have threat, can't quickly lower it. 3 options remain: Stop attacking, lowlevel damage (wand), keep on keeping on. return CastSpell(SHOOT, pTarget); } else // not elite { // Cast mana shield if no shield is already up if (MANA_SHIELD > 0 && m_ai->GetHealthPercent() < 70 && !m_bot->HasAura(MANA_SHIELD) && !m_bot->HasAura(ICE_BARRIER) && m_ai->SelfBuff(MANA_SHIELD)) return RETURN_CONTINUE; } } } // Mana check and replenishment if (EVOCATION && m_ai->GetManaPercent() <= 10 && !m_bot->HasSpellCooldown(EVOCATION) && !newTarget && m_ai->SelfBuff(EVOCATION)) return RETURN_CONTINUE; if (m_ai->GetManaPercent() <= 20) { Item* gem = FindManaGem(); if (gem) m_ai->UseItem(gem); } // If bot has frost/fire resist order use Frost/Fire Ward when available if (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_RESIST_FROST && FROST_WARD && !m_bot->HasSpellCooldown(FROST_WARD) && m_ai->SelfBuff(FROST_WARD)) return RETURN_CONTINUE; if (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_RESIST_FIRE && FIRE_WARD && !m_bot->HasSpellCooldown(FIRE_WARD) && m_ai->SelfBuff(FIRE_WARD)) return RETURN_CONTINUE; if (COUNTERSPELL > 0 && !m_bot->HasSpellCooldown(COUNTERSPELL) && pTarget->IsNonMeleeSpellCasted(true) && CastSpell(COUNTERSPELL, pTarget)) return RETURN_CONTINUE; // If Clearcasting is active, cast arcane missiles // Bot could also cast flamestrike or blizzard for free, but the AoE could break some crowd control // or add threat on mobs ignoring the bot currently, so only focus on the bot's current target if (m_bot->HasAura(CLEARCASTING_1) && ARCANE_MISSILES > 0 && CastSpell(ARCANE_MISSILES, pTarget)) { m_ai->SetIgnoreUpdateTime(3); return RETURN_CONTINUE; } switch (spec) { case MAGE_SPEC_FROST: if (COLD_SNAP && !m_bot->HasSpellCooldown(COLD_SNAP) && CheckFrostCooldowns() > 2 && m_ai->SelfBuff(COLD_SNAP)) // Clear frost spell cooldowns if bot has more than 2 active return RETURN_CONTINUE; if (CONE_OF_COLD > 0 && !m_bot->HasSpellCooldown(CONE_OF_COLD) && meleeReach) { // Cone of Cold does not require a target, so ensure that the bot faces the current one before casting m_ai->FaceTarget(pTarget); if (m_ai->CastSpell(CONE_OF_COLD)) return RETURN_CONTINUE; } if (FROSTBOLT > 0 && m_ai->In_Reach(pTarget,FROSTBOLT) && !pTarget->HasAura(FROSTBOLT, EFFECT_INDEX_0) && CastSpell(FROSTBOLT, pTarget)) return RETURN_CONTINUE; if (FROST_NOVA > 0 && !m_bot->HasSpellCooldown(FROST_NOVA) && meleeReach && !pTarget->HasAura(FROST_NOVA, EFFECT_INDEX_0) && CastSpell(FROST_NOVA, pTarget)) return RETURN_CONTINUE; // Default frost spec action if (FROSTBOLT > 0 && m_ai->In_Reach(pTarget,FROSTBOLT)) return CastSpell(FROSTBOLT, pTarget); /* if (BLIZZARD > 0 && m_ai->In_Reach(pTarget,BLIZZARD) && m_ai->GetAttackerCount() >= 5 && CastSpell(BLIZZARD, pTarget)) { m_ai->SetIgnoreUpdateTime(8); return RETURN_CONTINUE; } */ break; case MAGE_SPEC_FIRE: if (COMBUSTION > 0 && m_ai->SelfBuff(COMBUSTION)) return RETURN_CONTINUE; if (BLAST_WAVE > 0 && m_ai->GetAttackerCount() >= 3 && meleeReach && CastSpell(BLAST_WAVE, pTarget)) return RETURN_CONTINUE; // Try to have 3 scorch stacks to let tank build aggro while getting a nice crit% bonus if (IMPROVED_SCORCH > 0 && SCORCH > 0) { if (!pTarget->HasAura(FIRE_VULNERABILITY, EFFECT_INDEX_0) && CastSpell(SCORCH, pTarget)) // no stacks: cast it return RETURN_CONTINUE; else { SpellAuraHolder* holder = pTarget->GetSpellAuraHolder(FIRE_VULNERABILITY); if (holder && (holder->GetStackAmount() < 3) && CastSpell(SCORCH, pTarget)) return RETURN_CONTINUE; } } // At least 3 stacks of Scorch: cast an opening fireball if (FIREBALL > 0 && !pTarget->HasAura(FIREBALL, EFFECT_INDEX_1) && CastSpell(FIREBALL, pTarget)) return RETURN_CONTINUE; // 3 stacks of Scorch and fireball DoT: use fire blast if available if (FIRE_BLAST > 0 && !m_bot->HasSpellCooldown(FIRE_BLAST) && CastSpell(FIRE_BLAST, pTarget)) return RETURN_CONTINUE; // All DoTs, cooldowns used, try to maximise scorch stacks (5) to get a even nicer crit% bonus if (IMPROVED_SCORCH > 0 && SCORCH > 0) { SpellAuraHolder* holder = pTarget->GetSpellAuraHolder(FIRE_VULNERABILITY); if (holder && (holder->GetStackAmount() < 5) && CastSpell(SCORCH, pTarget)) return RETURN_CONTINUE; } // Default fire spec action if (FIREBALL > 0 && m_ai->In_Reach(pTarget,FIREBALL)) return CastSpell(FIREBALL, pTarget); /* if (FLAMESTRIKE > 0 && m_ai->In_Reach(pTarget,FLAMESTRIKE) && CastSpell(FLAMESTRIKE, pTarget)) return RETURN_CONTINUE; */ break; case MAGE_SPEC_ARCANE: if (ARCANE_POWER > 0 && !m_bot->HasSpellCooldown(ARCANE_POWER) && m_ai->IsElite(pTarget) && m_ai->CastSpell(ARCANE_POWER)) // Do not waste Arcane Power on normal NPCs as the bot is likely in a group return RETURN_CONTINUE; if (PRESENCE_OF_MIND > 0 && !m_bot->HasAura(PRESENCE_OF_MIND) && !m_bot->HasSpellCooldown(PRESENCE_OF_MIND) && m_ai->IsElite(pTarget) && m_ai->SelfBuff(PRESENCE_OF_MIND)) return RETURN_CONTINUE; // If bot has presence of mind active, cast long casting time spells if (PRESENCE_OF_MIND && m_bot->HasAura(PRESENCE_OF_MIND)) { // Instant Pyroblast, yeah! Tanks will probably hate this, but what do they know about power? Nothing... if (PYROBLAST > 0 && CastSpell(PYROBLAST, pTarget)) return RETURN_CONTINUE; if (FIREBALL > 0 && CastSpell(FIREBALL, pTarget)) return RETURN_CONTINUE; } if (ARCANE_EXPLOSION > 0 && m_ai->GetAttackerCount() >= 3 && meleeReach && CastSpell(ARCANE_EXPLOSION, pTarget)) return RETURN_CONTINUE; // Default arcane spec actions (yes, two fire spells) if (FIRE_BLAST > 0 && !m_bot->HasSpellCooldown(FIRE_BLAST) && CastSpell(FIRE_BLAST, pTarget)) return RETURN_CONTINUE; if (FIREBALL > 0 && m_ai->In_Reach(pTarget,FIREBALL)) return CastSpell(FIREBALL, pTarget); // If no fireball, arcane missiles if (ARCANE_MISSILES > 0 && CastSpell(ARCANE_MISSILES, pTarget)) { m_ai->SetIgnoreUpdateTime(3); return RETURN_CONTINUE; } break; } // No spec due to low level OR no spell found yet if (FROSTBOLT > 0 && m_ai->In_Reach(pTarget,FROSTBOLT) && !pTarget->HasAura(FROSTBOLT, EFFECT_INDEX_0) && CastSpell(FROSTBOLT, pTarget)) return RETURN_CONTINUE; if (FIREBALL > 0 && m_ai->In_Reach(pTarget,FIREBALL) && CastSpell(FIREBALL, pTarget)) // Very low levels return RETURN_CONTINUE; // Default: shoot with wand return CastSpell(SHOOT, pTarget); return RETURN_NO_ACTION_ERROR; // What? Not even Fireball or wand are available? } // end DoNextCombatManeuver
CombatManeuverReturns PlayerbotPaladinAI::HealPlayer(Player* target) { CombatManeuverReturns r = PlayerbotClassAI::HealPlayer(target); if (r != RETURN_NO_ACTION_OK) return r; if (!target->isAlive()) { if (REDEMPTION && m_ai->CastSpell(REDEMPTION, *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 (PURIFY > 0 && (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_NODISPEL) == 0) { uint32 DISPEL = CLEANSE > 0 ? CLEANSE : PURIFY; uint32 dispelMask = GetDispellMask(DISPEL_DISEASE); uint32 dispelMask2 = GetDispellMask(DISPEL_POISON); uint32 dispelMask3 = GetDispellMask(DISPEL_MAGIC); Unit::SpellAuraHolderMap const& auras = target->GetSpellAuraHolderMap(); for(Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) { SpellAuraHolder *holder = itr->second; if ((1 << holder->GetSpellProto()->Dispel) & dispelMask) { if (holder->GetSpellProto()->Dispel == DISPEL_DISEASE) { if (m_ai->CastSpell(DISPEL, *target)) return RETURN_CONTINUE; return RETURN_NO_ACTION_ERROR; } } else if ((1 << holder->GetSpellProto()->Dispel) & dispelMask2) { if (holder->GetSpellProto()->Dispel == DISPEL_POISON) { if (m_ai->CastSpell(DISPEL, *target)) return RETURN_CONTINUE; return RETURN_NO_ACTION_ERROR; } } else if ((1 << holder->GetSpellProto()->Dispel) & dispelMask3 & (DISPEL == CLEANSE)) { if (holder->GetSpellProto()->Dispel == DISPEL_MAGIC) { if (m_ai->CastSpell(DISPEL, *target)) return RETURN_CONTINUE; return RETURN_NO_ACTION_ERROR; } } } } // 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, FLASH_OF_LIGHT)) { m_bot->GetMotionMaster()->MoveFollow(target, 39.0f, m_bot->GetOrientation()); return RETURN_CONTINUE; } 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; if (hp < 10 && LAY_ON_HANDS && !m_bot->HasSpellCooldown(LAY_ON_HANDS) && m_ai->In_Reach(target,LAY_ON_HANDS) && m_ai->CastSpell(LAY_ON_HANDS, *target)) return RETURN_CONTINUE; // Target is a moderately wounded healer or a badly wounded not tank? Blessing of Protection! if (BLESSING_OF_PROTECTION > 0 && ((hp < 25 && (GetTargetJob(target) & JOB_HEAL)) || (hp < 15 && !(GetTargetJob(target) & JOB_TANK))) && !m_bot->HasSpellCooldown(BLESSING_OF_PROTECTION) && m_ai->In_Reach(target,BLESSING_OF_PROTECTION) && !target->HasAura(FORBEARANCE, EFFECT_INDEX_0) && !target->HasAura(BLESSING_OF_PROTECTION, EFFECT_INDEX_0) && !target->HasAura(DIVINE_PROTECTION, EFFECT_INDEX_0) && !target->HasAura(DIVINE_SHIELD, EFFECT_INDEX_0) && m_ai->CastSpell(BLESSING_OF_PROTECTION, *target)) return RETURN_CONTINUE; // Low HP : activate Divine Favor to make next heal a critical heal if (hp < 25 && DIVINE_FAVOR > 0 && !m_bot->HasAura(DIVINE_FAVOR, EFFECT_INDEX_0) && !m_bot->HasSpellCooldown(DIVINE_FAVOR) && m_ai->CastSpell (DIVINE_FAVOR, *m_bot)) return RETURN_CONTINUE; if (hp < 40 && FLASH_OF_LIGHT && m_ai->In_Reach(target,FLASH_OF_LIGHT) && m_ai->CastSpell(FLASH_OF_LIGHT, *target)) return RETURN_CONTINUE; if (hp < 60 && HOLY_SHOCK && m_ai->In_Reach(target,HOLY_SHOCK) && m_ai->CastSpell(HOLY_SHOCK, *target)) return RETURN_CONTINUE; if (hp < 90 && HOLY_LIGHT && m_ai->In_Reach(target,HOLY_LIGHT) && m_ai->CastSpell(HOLY_LIGHT, *target)) return RETURN_CONTINUE; return RETURN_NO_ACTION_UNKNOWN; } // end HealTarget
void UpdateAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (!m_pInstance) return; // Berserk if (m_uiBerserkTimer) { if (m_uiBerserkTimer <= uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_BERSERK) == CAST_OK) { DoScriptText(SAY_BERSERK, m_creature); m_uiBerserkTimer = 0; } } else m_uiBerserkTimer -= uiDiff; } if (m_uiGaseousBlightTimer) { if (m_uiGaseousBlightTimer <= uiDiff) { // two stage event; first trigger all the puddle stalkers around then set the room in gas switch (m_uiGaseousBlightStage) { case 0: if (Creature* pProfessor = m_pInstance->GetSingleCreatureFromStorage(NPC_PROFESSOR_PUTRICIDE)) { pProfessor->HandleEmote(EMOTE_ONESHOT_TALK_NOSHEATHE); pProfessor->CastSpell(pProfessor, SPELL_GASEOUS_BLIGHT_INIT, true); DoScriptText((m_pInstance->GetData(TYPE_ROTFACE) == DONE && m_pInstance->IsHeroicDifficulty()) ? SAY_BLIGHT_ROTFACE_DEAD : SAY_BLIGHT, pProfessor); } m_uiGaseousBlightTimer = 1000; break; case 1: if (DoCastSpellIfCan(m_creature, SPELL_GASEOUS_BLIGHT_1) == CAST_OK) m_uiGaseousBlightTimer = 0; break; } ++m_uiGaseousBlightStage; } else m_uiGaseousBlightTimer -= uiDiff; } // Inhale Blight and Pungent Blight if (m_uiInhaleBlightTimer < uiDiff) { SpellAuraHolder* pHolder = m_creature->GetSpellAuraHolder(m_pInstance->Is25ManDifficulty() ? SPELL_INHALED_BLIGHT_25 : SPELL_INHALED_BLIGHT_10); // inhale the gas or if already have 3 stacks - release it if (pHolder && pHolder->GetStackAmount() >= 3) { if (DoCastSpellIfCan(m_creature, SPELL_PUNGENT_BLIGHT) == CAST_OK) { DoScriptText(SAY_PUNGUENT_BLIGHT, m_creature); m_uiInhaleBlightTimer = 38000; } } else { if (DoCastSpellIfCan(m_creature, SPELL_INHALE_BLIGHT) == CAST_OK) m_uiInhaleBlightTimer = 36000; } } else m_uiInhaleBlightTimer -= uiDiff; // Gas Spore if (m_uiGasSporeTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_GAS_SPORE) == CAST_OK) { DoScriptText(EMOTE_SPORES, m_creature); m_uiGasSporeTimer = 40000; } } else m_uiGasSporeTimer -= uiDiff; // Vile Gas if (m_uiVileGasTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_VILE_GAS) == CAST_OK) m_uiVileGasTimer = 30000; } else m_uiVileGasTimer -= uiDiff; // Heroic spells if (m_pInstance->IsHeroicDifficulty()) { if (m_uiMalleableGooTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_MALLEABLE_GOO_SUMMON) == CAST_OK) m_uiMalleableGooTimer = 15000; } else m_uiMalleableGooTimer -= uiDiff; } DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; // Berserk if (m_uiBerserkTimer <= uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_BERSERK) == CAST_OK) { DoScriptText(SAY_BERSERK, m_creature); m_uiBerserkTimer = 5 * MINUTE * IN_MILLISECONDS; } } else m_uiBerserkTimer -= uiDiff; // Inhale Blight and Pungent Blight if (m_uiInhaleBlightTimer <= uiDiff) { SpellAuraHolder* holder = m_creature->GetSpellAuraHolder(SPELL_INHALED_BLIGHT_10); if (!holder) holder = m_creature->GetSpellAuraHolder(SPELL_INHALED_BLIGHT_25); // inhale the gas or if already have 3 stacks - release it if (holder && holder->GetStackAmount() >= 3) { if (DoCastSpellIfCan(m_creature, SPELL_PUNGENT_BLIGHT) == CAST_OK) { DoScriptText(SAY_PUNGUENT_BLIGHT_EMOTE, m_creature); DoScriptText(SAY_PUNGUENT_BLIGHT, m_creature); m_uiInhaleBlightTimer = 35000; } } else if (DoCastSpellIfCan(m_creature, SPELL_INHALE_BLIGHT) == CAST_OK) { if (m_pInstance) { if (Creature* pProfessor = m_pInstance->GetSingleCreatureFromStorage(NPC_PROFESSOR_PUTRICIDE)) DoScriptText(SAY_BLIGHT, pProfessor); } m_uiInhaleBlightTimer = 30000; } } else m_uiInhaleBlightTimer -= uiDiff; // Gas Spore if (m_uiGasSporeTimer <= uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_GAS_SPORE) == CAST_OK) { DoScriptText(SAY_SPORE, m_creature); m_uiGasSporeTimer = 40000; } } else m_uiGasSporeTimer -= uiDiff; // Vile Gas if (m_uiVileGasTimer <= uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_VILE_GAS_SUMMON, CAST_TRIGGERED) == CAST_OK) { if (DoCastSpellIfCan(m_creature, SPELL_VILE_GAS) == CAST_OK) m_uiVileGasTimer = 30000; } } else m_uiVileGasTimer -= uiDiff; DoMeleeAttackIfReady(); }
CombatManeuverReturns PlayerbotPaladinAI::HealPlayer(Player* target) { CombatManeuverReturns r = PlayerbotClassAI::HealPlayer(target); if (r != RETURN_NO_ACTION_OK) return r; if (!target->isAlive()) { if (REDEMPTION && m_ai->CastSpell(REDEMPTION, *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 (PURIFY > 0 && (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_NODISPEL) == 0) { uint32 DISPEL = CLEANSE > 0 ? CLEANSE : PURIFY; uint32 dispelMask = GetDispellMask(DISPEL_DISEASE); uint32 dispelMask2 = GetDispellMask(DISPEL_POISON); uint32 dispelMask3 = GetDispellMask(DISPEL_MAGIC); Unit::SpellAuraHolderMap const& auras = target->GetSpellAuraHolderMap(); for (Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) { SpellAuraHolder* holder = itr->second; if ((1 << holder->GetSpellProto()->Dispel) & dispelMask) { if (holder->GetSpellProto()->Dispel == DISPEL_DISEASE) { if (m_ai->CastSpell(DISPEL, *target)) return RETURN_CONTINUE; return RETURN_NO_ACTION_ERROR; } } else if ((1 << holder->GetSpellProto()->Dispel) & dispelMask2) { if (holder->GetSpellProto()->Dispel == DISPEL_POISON) { if (m_ai->CastSpell(DISPEL, *target)) return RETURN_CONTINUE; return RETURN_NO_ACTION_ERROR; } } else if ((1 << holder->GetSpellProto()->Dispel) & dispelMask3 & (DISPEL == CLEANSE)) { if (holder->GetSpellProto()->Dispel == DISPEL_MAGIC) { if (m_ai->CastSpell(DISPEL, *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; if (hp < 25 && m_ai->CastSpell(LAY_ON_HANDS, *target)) return RETURN_CONTINUE; // You probably want to save this for tank/healer trouble if (hp < 30 && HAND_OF_PROTECTION > 0 && !target->HasAura(FORBEARANCE, EFFECT_INDEX_0) && !target->HasAura(HAND_OF_PROTECTION, EFFECT_INDEX_0) && !target->HasAura(DIVINE_PROTECTION, EFFECT_INDEX_0) && !target->HasAura(DIVINE_SHIELD, EFFECT_INDEX_0) && (GetTargetJob(target) & (JOB_HEAL | JOB_TANK)) && m_ai->CastSpell(HAND_OF_PROTECTION, *target)) return RETURN_CONTINUE; // Isn't this more of a group heal spell? if (hp < 40 && m_ai->CastSpell(FLASH_OF_LIGHT, *target)) return RETURN_CONTINUE; if (hp < 60 && m_ai->CastSpell(HOLY_SHOCK, *target)) return RETURN_CONTINUE; if (hp < 90 && m_ai->CastSpell(HOLY_LIGHT, *target)) return RETURN_CONTINUE; return RETURN_NO_ACTION_UNKNOWN; } // end HealTarget
bool BSWScriptedAI::_doRemove(uint8 m_uiSpellIdx, Unit* pTarget, uint8 index) { SpellTable* pSpell = &m_BossSpell[m_uiSpellIdx]; debug_log("BSW: Removing effects of spell %u type %u",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget); switch (pSpell->m_CastTarget) { case DO_NOTHING: return true; case SUMMON_NORMAL: case SUMMON_TEMP: case SUMMON_INSTANT: return false; case CAST_ON_SELF: case APPLY_AURA_SELF: pTarget = m_creature; break; case CAST_ON_SUMMONS: case CAST_ON_VICTIM: case CAST_ON_BOTTOMAGGRO: case CAST_ON_TARGET: case APPLY_AURA_TARGET: if (!pTarget) return false; break; case CAST_ON_RANDOM: case CAST_ON_RANDOM_PLAYER: case APPLY_AURA_ALLPLAYERS: case CAST_ON_ALLPLAYERS: { Map::PlayerList const& pPlayers = pMap->GetPlayers(); for (Map::PlayerList::const_iterator itr = pPlayers.begin(); itr != pPlayers.end(); ++itr) { pTarget = itr->getSource(); if (_hasAura(m_uiSpellIdx,pTarget)) pTarget->RemoveAurasDueToSpell(pSpell->m_uiSpellEntry[currentDifficulty]); } return true; } break; default: debug_log("BSW: FAILED Removing effects of spell %u type %u - unsupported type",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget); return false; } if (!pTarget || !pTarget->IsInMap(m_creature) || !pTarget->isAlive()) { error_log("BSW: FAILED removing effects of spell number %u - no target or target not in map or target is dead",pSpell->m_uiSpellEntry[currentDifficulty]); return false; } if (index == EFFECT_INDEX_ALL) { pTarget->RemoveAurasDueToSpell(pSpell->m_uiSpellEntry[currentDifficulty]); return true; } if (_auraCount(m_uiSpellIdx,pTarget,(SpellEffectIndex)index) > 1) { SpellAuraHolder *holder = pTarget->GetSpellAuraHolder(pSpell->m_uiSpellEntry[currentDifficulty], pTarget->GetGUID()); if (holder->ModStackAmount(-1)) { pTarget->RemoveSpellAuraHolder(holder, AURA_REMOVE_BY_DISPEL); return true; } else return false; } else pTarget->RemoveAurasDueToSpell(pSpell->m_uiSpellEntry[currentDifficulty]); return true; };