static bool HandleLearnAllGMCommand(ChatHandler* handler, const char* /*args*/) { for (uint32 i = 0; i < GetSpellStore()->GetNumRows(); ++i) { SpellEntry const* spellInfo = sSpellStore.LookupEntry(i); if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer(), false)) continue; if (!sSpellMgr->IsSkillTypeSpell(i, SKILL_INTERNAL)) continue; handler->GetSession()->GetPlayer()->learnSpell(i, false); } handler->SendSysMessage(LANG_LEARNING_GM_SKILLS); return true; }
boss_netherspiteAI(Creature* c) : ScriptedAI(c) { pInstance = c->GetInstanceData(); for (int i=0; i<3; ++i) { PortalGUID[i] = 0; BeamTarget[i] = 0; BeamerGUID[i] = 0; } // need core fix for (int i=0; i<3; ++i) { if (SpellEntry *spell = (SpellEntry*)GetSpellStore()->LookupEntry(PlayerBuff[i])) spell->AttributesEx |= SPELL_ATTR_EX_NEGATIVE; } }
bool ItemUse_item_petrov_cluster_bombs(Player* pPlayer, Item* pItem, const SpellCastTargets &pTargets) { if (pPlayer->GetZoneId() != ZONE_ID_HOWLING) return false; if (!pPlayer->GetTransport() || pPlayer->GetAreaId() != AREA_ID_SHATTERED_STRAITS) { pPlayer->SendEquipError(EQUIP_ERR_NONE, pItem, NULL); if (const SpellEntry* pSpellInfo = GetSpellStore()->LookupEntry(SPELL_PETROV_BOMB)) Spell::SendCastResult(pPlayer, pSpellInfo, 1, SPELL_FAILED_NOT_HERE); return true; } return false; }
CanCastResult BossSpellWorker::_DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags, uint64 uiOriginalCasterGUID) { Unit* pCaster = boss; if (!pTarget) return CAST_FAIL_OTHER; if (uiCastFlags & CAST_FORCE_TARGET_SELF) pCaster = pTarget; // Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered if (!pCaster->IsNonMeleeSpellCasted(false) || (uiCastFlags & (CAST_TRIGGERED | CAST_INTERRUPT_PREVIOUS))) { if (const SpellEntry* pSpell = GetSpellStore()->LookupEntry(uiSpell)) { // If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them if (uiCastFlags & CAST_AURA_NOT_PRESENT) { if (pTarget->HasAura(uiSpell)) return CAST_FAIL_TARGET_AURA; } // Check if cannot cast spell if (!(uiCastFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST))) { CanCastResult castResult = _CanCastSpell(pTarget, pSpell, uiCastFlags & CAST_TRIGGERED); if (castResult != CAST_OK) return castResult; } // Interrupt any previous spell if (uiCastFlags & CAST_INTERRUPT_PREVIOUS && pCaster->IsNonMeleeSpellCasted(false)) pCaster->InterruptNonMeleeSpells(false); pCaster->CastSpell(pTarget, pSpell, uiCastFlags & CAST_TRIGGERED, NULL, NULL, uiOriginalCasterGUID); return CAST_OK; } else { error_log("BSW: DoCastSpellIfCan by creature entry %u attempt to cast spell %u but spell does not exist.", boss->GetEntry(), uiSpell); return CAST_FAIL_OTHER; } } else return CAST_FAIL_IS_CASTING; }
boss_nalorakkAI(Creature *c) : ScriptedAI(c) { MoveEvent = true; MovePhase = 0; pInstance = (c->GetInstanceData()); SpellEntry *TempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_MANGLE); if(TempSpell) { TempSpell->EffectImplicitTargetA[1] = TARGET_UNIT_TARGET_ENEMY; } wLoc.coord_x = NalorakkWay[7][0]; wLoc.coord_y = NalorakkWay[7][1]; wLoc.coord_z = NalorakkWay[7][2]; wLoc.orientation = 0; wLoc.mapid = m_creature->GetMapId(); m_creature->setActive(true); }
bool ItemUse_item_Capteur_Tellurique(Player* pPlayer, Item* pItem, const SpellCastTargets &pTargets) { if(pPlayer->GetAreaId() == 4157) { if(pPlayer->GetPositionZ() < 185.0f) { pPlayer->TeleportTo(pPlayer->GetMapId(),3329.524f,2543.395f,197.317f,4.950f); pPlayer->KilledMonsterCredit(27853,0); } else pPlayer->TeleportTo(pPlayer->GetMapId(),3414.0f,2363.01f,37.911f,3.102f); } else { Spell::SendCastResult(pPlayer, GetSpellStore()->LookupEntry(47097), 1, SPELL_FAILED_INCORRECT_AREA); return false; } return true; }
void EnfeebleHealthEffect() { const SpellEntry *info = GetSpellStore()->LookupEntry(SPELL_ENFEEBLE_EFFECT); if (!info) return; ThreatList const& tList = m_creature->getThreatManager().getThreatList(); std::vector<Unit *> targets; if (tList.empty()) return; //begin + 1 , so we don't target the one with the highest threat ThreatList::const_iterator itr = tList.begin(); std::advance(itr, 1); for(; itr!= tList.end(); ++itr) //store the threat list in a different container { Unit *target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); //only on alive players if (target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER) targets.push_back(target); } //cut down to size if we have more than 5 targets while(targets.size() > 5) targets.erase(targets.begin()+rand()%targets.size()); int i = 0; for(std::vector<Unit *>::iterator iter = targets.begin(); iter!= targets.end(); ++iter, ++i) { Unit *target = *iter; if (target) { enfeeble_targets[i] = target->GetGUID(); enfeeble_health[i] = target->GetHealth(); target->CastSpell(target, SPELL_ENFEEBLE, true, 0, 0, m_creature->GetGUID()); target->SetHealth(1); } } }
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; }
bool GOGossipSelect_go_ulduar_teleporter(Player *pPlayer, GameObject* pGo, uint32 sender, uint32 action) { int32 damage = 0; if(sender != GOSSIP_SENDER_MAIN) return true; if(pPlayer->IsInCombat()) return true; 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)) { SpellAuraHolderPtr holder = CreateSpellAuraHolder(spell, pPlayer, pPlayer); Aura* aura = holder->CreateAura(AURA_CLASS_AURA, EFFECT_INDEX_2, NULL, holder, pPlayer, pPlayer, NULL); pPlayer->AddSpellAuraHolder(holder); } pPlayer->CLOSE_GOSSIP_MENU(); return true; }
bool PlayerbotClassAI::castDispel (uint32 dispelSpell, Unit *dTarget, bool checkFirst, bool castExistingAura, bool skipFriendlyCheck, bool skipEquipStanceCheck) { if (dispelSpell == 0 || !dTarget ) return false; //if (!canCast(dispelSpell, dTarget, true)) return false; //Needless cpu cycles wasted, usually a playerbot can cast a dispell const SpellEntry *dSpell = GetSpellStore()->LookupEntry(dispelSpell); if (!dSpell) return false; for (uint8 i = 0 ; i < MAX_SPELL_EFFECTS ; ++i) { if (dSpell->Effect[i] != (uint32)SPELL_EFFECT_DISPEL) continue; uint32 dispel_type = dSpell->EffectMiscValue[i]; uint32 dispelMask = GetDispellMask(DispelType(dispel_type)); Unit::AuraMap const& auras = dTarget->GetOwnedAuras(); for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); itr++) { Aura * aura = itr->second; AuraApplication * aurApp = aura->GetApplicationOfTarget(dTarget->GetGUID()); if (!aurApp) continue; if ((1<<aura->GetSpellProto()->Dispel) & dispelMask) { if(aura->GetSpellProto()->Dispel == DISPEL_MAGIC) { bool positive = aurApp->IsPositive() ? (!(aura->GetSpellProto()->AttributesEx & SPELL_ATTR0_UNK7)) : false; // do not remove positive auras if friendly target // negative auras if non-friendly target if(positive == dTarget->IsFriendlyTo(GetPlayerBot())) continue; } // If there is a successfull match return, else continue searching. if (CastSpell(dSpell, dTarget, checkFirst, castExistingAura, skipFriendlyCheck, skipEquipStanceCheck)) { return true; } } } } return false; }
void CastDoom() { SpellEntry *spellInfo = (SpellEntry *)GetSpellStore()->LookupEntry(SPELL_DOOM); if (spellInfo) //target without tank if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1)) { if (pTarget->GetTypeId() == TYPEID_PLAYER) { for(uint8 i=0; i< MAX_EFFECT_INDEX; ++i) { uint8 eff = spellInfo->Effect[SpellEffectIndex(i)]; if (eff >= TOTAL_SPELL_EFFECTS) continue; //uint8 i=1; /*pTarget->AddAura(new AzgalorDoom(spellInfo, SpellEffectIndex(i), NULL, pTarget, pTarget));*/ } } else DoomTimer = 1000; } }
void CastMark() { SpellEntry *spellInfo = (SpellEntry *)GetSpellStore()->LookupEntry(SPELL_MARK); if (spellInfo) { std::list<HostileReference *> t_list = m_creature->getThreatManager().getThreatList(); for(std::list<HostileReference *>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) { Unit *target = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid()); if (target && target->GetTypeId() == TYPEID_PLAYER && target->getPowerType() == POWER_MANA) { for(uint32 i=0; i < MAX_EFFECT_INDEX; ++i) { uint8 eff = spellInfo->Effect[SpellEffectIndex(i)]; if (eff >= TOTAL_SPELL_EFFECTS) continue; /*target->AddAura(new KazrogalMark(spellInfo, SpellEffectIndex(i), NULL, target, target));*/ } } } } }
void EnfeebleHealthEffect() { const SpellEntry *info = GetSpellStore()->LookupEntry( SPELL_ENFEEBLE_EFFECT); if (!info) return; std::list<HostileReference *> t_list = me->getThreatManager().getThreatList(); std::vector<Unit *> targets; if (!t_list.size()) return; //begin + 1, so we don't target the one with the highest threat std::list<HostileReference *>::const_iterator itr = t_list.begin(); std::advance(itr, 1); for (; itr != t_list.end(); ++itr) //store the threat list in a different container if (Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid())) if (pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) targets.push_back(pTarget); //cut down to size if we have more than 5 targets while (targets.size() > 5) targets.erase(targets.begin() + rand() % targets.size()); uint32 i = 0; for (std::vector<Unit *>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter, ++i) if (Unit *pTarget = *iter) { enfeeble_targets[i] = pTarget->GetGUID(); enfeeble_health[i] = pTarget->GetHealth(); pTarget->CastSpell(pTarget, SPELL_ENFEEBLE, true, 0, 0, me->GetGUID()); pTarget->SetHealth(1); } }
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; };
// some targeting issues with the spell, so use this workaround as temporary solution void DoWorkaroundForQuestCredit() { Map* pMap = me->GetMap(); if (!pMap || pMap->IsHeroic()) return; Map::PlayerList const &lList = pMap->GetPlayers(); if (lList.isEmpty()) return; SpellEntry const* pSpell = GetSpellStore()->LookupEntry( SPELL_ORB_KILL_CREDIT); for (Map::PlayerList::const_iterator i = lList.begin(); i != lList.end(); ++i) { if (Player* pPlayer = i->getSource()) { if (pSpell && pSpell->EffectMiscValue[0]) pPlayer->KilledMonsterCredit(pSpell->EffectMiscValue[0], 0); } } }
void UpdateAI(const uint32 diff) { if(!me->IsNonMeleeSpellCasted(false) && !me->isInCombat()) { if(OOCTimer < diff) { HandleOffCombatEffects(); OOCTimer = 10000; } else OOCTimer -= diff; } if(!UpdateVictim()) return; if(Frostbolt_Timer < diff) { AddSpellToCast(me->getVictim(), SPELL_FROSTBOLT); Frostbolt_Timer = SpellMgr::GetSpellCastTime(GetSpellStore()->LookupEntry(SPELL_FROSTBOLT))-(diff+100); } else Frostbolt_Timer -= diff; if(Arcane_Nova_Timer < diff) { ClearCastQueue(); AddSpellToCast(SPELL_ARCANE_NOVA, CAST_SELF); Arcane_Nova_Timer = urand(16000, 20000); } else Arcane_Nova_Timer -= diff; CheckCasterNoMovementInRange(diff, 35.0); CastNextSpellIfAnyAndReady(); DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if (!Vorpil) { me->DealDamage(me, me->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); return; } if (move <= diff) { if (sacrificed) { SpellEntry* spell = (SpellEntry*)GetSpellStore()->LookupEntry(HeroicMode ? H_SPELL_EMPOWERING_SHADOWS : SPELL_EMPOWERING_SHADOWS); if (spell) Vorpil->AddAura(new EmpoweringShadowsAura(spell, 0, NULL, Vorpil, me)); Vorpil->SetHealth(Vorpil->GetHealth() + Vorpil->GetMaxHealth() / 25); DoCast(me, SPELL_SHADOW_NOVA, true); me->DealDamage(me, me->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); return; } me->GetMotionMaster()->MoveFollow(Vorpil, 0, 0); if (me->GetDistance(Vorpil) < 3) { DoCast(me, SPELL_SACRIFICE, false); sacrificed = true; move = 500; return; } if (!Vorpil->IsInCombat() || Vorpil->isDead()) { me->DealDamage(me, me->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); return; } move = 1000; } else move -= diff; }
void FillSpellSummary() { SpellSummary = new TSpellSummary[GetSpellStore()->GetNumRows()]; SpellEntry const* TempSpell; for (int i=0; i < GetSpellStore()->GetNumRows(); i++) { SpellSummary[i].Effects = 0; SpellSummary[i].Targets = 0; TempSpell = GetSpellStore()->LookupEntry(i); //This spell doesn't exist if (!TempSpell) continue; for (int j=0; j<3; j++) { //Spell targets self if (TempSpell->EffectImplicitTargetA[j] == TARGET_SELF) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SELF-1); //Spell targets a single enemy if (TempSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE || TempSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_ENEMY_COORDINATES) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY-1); //Spell targets AoE at enemy if (TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA || TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || TempSpell->EffectImplicitTargetA[j] == TARGET_CASTER_COORDINATES || TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_ENEMY-1); //Spell targets an enemy if (TempSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE || TempSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_ENEMY_COORDINATES || TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA || TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || TempSpell->EffectImplicitTargetA[j] == TARGET_CASTER_COORDINATES || TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_ENEMY-1); //Spell targets a single friend(or self) if (TempSpell->EffectImplicitTargetA[j] == TARGET_SELF || TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND || TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND-1); //Spell targets aoe friends if (TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER || TempSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY || TempSpell->EffectImplicitTargetA[j] == TARGET_CASTER_COORDINATES) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_FRIEND-1); //Spell targets any friend(or self) if (TempSpell->EffectImplicitTargetA[j] == TARGET_SELF || TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND || TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY || TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER || TempSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY || TempSpell->EffectImplicitTargetA[j] == TARGET_CASTER_COORDINATES) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_FRIEND-1); //Make sure that this spell includes a damage effect if (TempSpell->Effect[j] == SPELL_EFFECT_SCHOOL_DAMAGE || TempSpell->Effect[j] == SPELL_EFFECT_INSTAKILL || TempSpell->Effect[j] == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE || TempSpell->Effect[j] == SPELL_EFFECT_HEALTH_LEECH) SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_DAMAGE-1); //Make sure that this spell includes a healing effect (or an apply aura with a periodic heal) if (TempSpell->Effect[j] == SPELL_EFFECT_HEAL || TempSpell->Effect[j] == SPELL_EFFECT_HEAL_MAX_HEALTH || TempSpell->Effect[j] == SPELL_EFFECT_HEAL_MECHANICAL || (TempSpell->Effect[j] == SPELL_EFFECT_APPLY_AURA && TempSpell->EffectApplyAuraName[j]== 8)) SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_HEALING-1); //Make sure that this spell applies an aura if (TempSpell->Effect[j] == SPELL_EFFECT_APPLY_AURA) SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_AURA-1); } } }
SpellEntry const* ScriptedAI::SelectSpell(Unit* Target, int32 School, int32 Mechanic, SelectTarget Targets, uint32 PowerCostMin, uint32 PowerCostMax, float RangeMin, float RangeMax, SelectEffect Effects) { //No target so we can't cast if (!Target) return false; //Silenced so we can't cast if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) return false; //Using the extended script system we first create a list of viable spells SpellEntry const* Spell[4]; Spell[0] = 0; Spell[1] = 0; Spell[2] = 0; Spell[3] = 0; uint32 SpellCount = 0; SpellEntry const* TempSpell; SpellRangeEntry const* TempRange; //Check if each spell is viable(set it to null if not) for (uint32 i = 0; i < 4; i++) { TempSpell = GetSpellStore()->LookupEntry(m_creature->m_spells[i]); //This spell doesn't exist if (!TempSpell) continue; // Targets and Effects checked first as most used restrictions //Check the spell targets if specified if (Targets && !(SpellSummary[m_creature->m_spells[i]].Targets & (1 << (Targets-1)))) continue; //Check the type of spell if we are looking for a specific spell type if (Effects && !(SpellSummary[m_creature->m_spells[i]].Effects & (1 << (Effects-1)))) continue; //Check for school if specified if (School >= 0 && TempSpell->SchoolMask & School) continue; //Check for spell mechanic if specified if (Mechanic >= 0 && TempSpell->Mechanic != Mechanic) continue; //Make sure that the spell uses the requested amount of power if (PowerCostMin && TempSpell->manaCost < PowerCostMin) continue; if (PowerCostMax && TempSpell->manaCost > PowerCostMax) continue; //Continue if we don't have the mana to actually cast this spell if (TempSpell->manaCost > m_creature->GetPower((Powers)TempSpell->powerType)) continue; //Get the Range TempRange = GetSpellRangeStore()->LookupEntry(TempSpell->rangeIndex); //Spell has invalid range store so we can't use it if (!TempRange) continue; //Check if the spell meets our range requirements if (RangeMin && TempRange->maxRange < RangeMin) continue; if (RangeMax && TempRange->maxRange > RangeMax) continue; //Check if our target is in range if (m_creature->IsWithinDistInMap(Target, TempRange->minRange) || !m_creature->IsWithinDistInMap(Target, TempRange->maxRange)) continue; //All good so lets add it to the spell list Spell[SpellCount] = TempSpell; SpellCount++; } //We got our usable spells so now lets randomly pick one if (!SpellCount) return NULL; return Spell[rand()%SpellCount]; }
bool EffectDummyCreature_spell_dummy_npc(Unit* pCaster, uint32 uiSpellId, SpellEffectIndex uiEffIndex, Creature* pCreatureTarget) { switch (uiSpellId) { case SPELL_ADMINISTER_ANTIDOTE: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->GetEntry() != NPC_HELBOAR) return true; // possible needs check for quest state, to not have any effect when quest really complete pCreatureTarget->UpdateEntry(NPC_DREADTUSK); return true; } return true; } case SPELL_APPLY_SALVE: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() != TYPEID_PLAYER) return true; if (pCreatureTarget->GetEntry() != NPC_SICKLY_DEER && pCreatureTarget->GetEntry() != NPC_SICKLY_GAZELLE) return true; // Update entry, remove aura, set the kill credit and despawn uint32 uiUpdateEntry = pCreatureTarget->GetEntry() == NPC_SICKLY_DEER ? NPC_CURED_DEER : NPC_CURED_GAZELLE; pCreatureTarget->RemoveAurasDueToSpell(SPELL_SICKLY_AURA); pCreatureTarget->UpdateEntry(uiUpdateEntry); ((Player*)pCaster)->KilledMonsterCredit(uiUpdateEntry); pCreatureTarget->ForcedDespawn(20000); return true; } return true; } case SPELL_DARKMENDER_TINCTURE: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() != TYPEID_PLAYER) return true; // TODO: find/fix visual for effect, no related spells found doing this pCreatureTarget->CastSpell(pCreatureTarget, SPELL_SUMMON_CORRUPTED_SCARLET, true); ((Player*)pCaster)->KilledMonsterCredit(NPC_CORPSES_RISE_CREDIT_BUNNY); pCreatureTarget->ForcedDespawn(); return true; } return true; } case SPELL_DISCIPLINING_ROD: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->getStandState() == UNIT_STAND_STATE_STAND) return true; switch (urand(1, 2)) { case 1: { switch (urand(1, 3)) { case 1: DoScriptText(SAY_RAND_ATTACK1, pCreatureTarget); break; case 2: DoScriptText(SAY_RAND_ATTACK2, pCreatureTarget); break; case 3: DoScriptText(SAY_RAND_ATTACK3, pCreatureTarget); break; } pCreatureTarget->SetStandState(UNIT_STAND_STATE_STAND); pCreatureTarget->AI()->AttackStart(pCaster); break; } case 2: { switch (urand(1, 3)) { case 1: DoScriptText(SAY_RAND_WORK1, pCreatureTarget); break; case 2: DoScriptText(SAY_RAND_WORK2, pCreatureTarget); break; case 3: DoScriptText(SAY_RAND_WORK3, pCreatureTarget); break; } pCreatureTarget->SetStandState(UNIT_STAND_STATE_STAND); pCreatureTarget->HandleEmote(EMOTE_STATE_WORK); break; } } return true; } return true; } case SPELL_INOCULATE_OWLKIN: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->GetEntry() != NPC_OWLKIN) return true; pCreatureTarget->UpdateEntry(NPC_OWLKIN_INOC); ((Player*)pCaster)->KilledMonsterCredit(NPC_OWLKIN_INOC); // set despawn timer, since we want to remove creature after a short time pCreatureTarget->ForcedDespawn(15000); return true; } return true; } case SPELL_LIQUID_FIRE: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() == TYPEID_PLAYER) { if (pCreatureTarget->HasAura(SPELL_LIQUID_FIRE_AURA)) return true; if (pCreatureTarget->GetEntry() == NPC_ELK) { pCreatureTarget->CastSpell(pCreatureTarget, SPELL_LIQUID_FIRE_AURA, true); ((Player*)pCaster)->KilledMonsterCredit(NPC_ELK_BUNNY); } else if (pCreatureTarget->GetEntry() == NPC_GRIZZLY) { pCreatureTarget->CastSpell(pCreatureTarget, SPELL_LIQUID_FIRE_AURA, true); ((Player*)pCaster)->KilledMonsterCredit(NPC_GRIZZLY_BUNNY); } } return true; } return true; } case SPELL_MODIFIED_MOJO: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->GetEntry() != NPC_PROPHET_OF_SSERATUS) return true; // Apparently done before updateEntry, so need to make a way to handle that // "Mmm, more mojo" // "%s drinks the Mojo" // "NOOOOOOOOOOOOooooooo...............!" pCreatureTarget->UpdateEntry(NPC_WEAK_PROPHET_OF_SSERATUS); return true; } return true; } case SPELL_FEL_SIPHON_DUMMY: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->GetEntry() != NPC_FELBLOOD_INITIATE) return true; pCreatureTarget->UpdateEntry(NPC_EMACIATED_FELBLOOD); return true; } return true; } case SPELL_SACRED_CLEANSING: { if (uiEffIndex == EFFECT_INDEX_1) { if (pCreatureTarget->GetEntry() != NPC_MORBENT) return true; pCreatureTarget->UpdateEntry(NPC_WEAKENED_MORBENT); return true; } return true; } case SPELL_SEEDS_OF_NATURES_WRATH: { if (uiEffIndex == EFFECT_INDEX_0) { uint32 uiNewEntry = 0; switch (pCreatureTarget->GetEntry()) { case NPC_REANIMATED_FROSTWYRM: uiNewEntry = NPC_WEAK_REANIMATED_FROSTWYRM; break; case NPC_TURGID: uiNewEntry = NPC_WEAK_TURGID; break; case NPC_DEATHGAZE: uiNewEntry = NPC_WEAK_DEATHGAZE; break; } if (uiNewEntry) pCreatureTarget->UpdateEntry(uiNewEntry); return true; } return true; } case SPELL_STRENGTH_ANCIENTS: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() == TYPEID_PLAYER) { if (urand(0, 1)) { DoScriptText(EMOTE_AGGRO, pCreatureTarget); pCreatureTarget->setFaction(FACTION_HOSTILE); pCreatureTarget->AI()->AttackStart(pCaster); } else { DoScriptText(EMOTE_CREATE, pCreatureTarget); pCaster->CastSpell(pCaster, SPELL_CREATE_BARK_WALKERS, true); pCreatureTarget->ForcedDespawn(5000); } } return true; } return true; } case SPELL_TAG_MURLOC_PROC: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->GetEntry() == NPC_BLACKSILT_MURLOC) pCreatureTarget->UpdateEntry(NPC_TAGGED_MURLOC); } return true; } case SPELL_THROW_BOULDER: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() != TYPEID_PLAYER) return true; if (pCreatureTarget->GetEntry() != NPC_IRON_RUNESHAPER && pCreatureTarget->GetEntry() != NPC_RUNE_REAVER) return true; pCreatureTarget->CastSpell(pCreatureTarget, SPELL_BOULBER_IMPACT, true); pCaster->CastSpell(pCaster, SPELL_BOULDER_TOSS_CREDIT, true); return true; } return true; } case SPELL_ULTRASONIC_SCREWDRIVER: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->IsCorpse()) { uint32 newSpellId = 0; switch (pCreatureTarget->GetEntry()) { case NPC_COLLECT_A_TRON: newSpellId = SPELL_SUMMON_COLLECT_A_TRON; break; case NPC_DEFENDO_TANK: newSpellId = SPELL_SUMMON_DEFENDO_TANK; break; case NPC_SCAVENGE_A8: newSpellId = SPELL_SUMMON_SCAVENGE_A8; break; case NPC_SCAVENGE_B6: newSpellId = SPELL_SUMMON_SCAVENGE_B6; break; case NPC_SENTRY_BOT: newSpellId = SPELL_SUMMON_SENTRY_BOT; break; } if (const SpellEntry* pSpell = GetSpellStore()->LookupEntry(newSpellId)) { pCaster->CastSpell(pCreatureTarget, pSpell->Id, true); if (Pet* pPet = pCaster->FindGuardianWithEntry(pSpell->GetEffectMiscValue(SpellEffectIndex(uiEffIndex)))) pPet->CastSpell(pCaster, SPELL_REPROGRAM_KILL_CREDIT, true); pCreatureTarget->ForcedDespawn(); } } return true; } return true; } case SPELL_ORB_OF_MURLOC_CONTROL: { pCreatureTarget->CastSpell(pCaster, SPELL_GREENGILL_SLAVE_FREED, true); // Freed Greengill Slave pCreatureTarget->UpdateEntry(NPC_FREED_GREENGILL_SLAVE); pCreatureTarget->CastSpell(pCreatureTarget, SPELL_ENRAGE, true); return true; } case SPELL_FUMPING: { if (uiEffIndex == EFFECT_INDEX_2) { switch (urand(0, 2)) { case 0: { pCaster->CastSpell(pCreatureTarget, SPELL_SUMMON_HAISHULUD, true); break; } case 1: { for (int i = 0; i < 2; ++i) { if (Creature* pSandGnome = pCaster->SummonCreature(NPC_SAND_GNOME, pCreatureTarget->GetPositionX(), pCreatureTarget->GetPositionY(), pCreatureTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_OOC_DESPAWN, 30000)) pSandGnome->AI()->AttackStart(pCaster); } break; } case 2: { for (int i = 0; i < 2; ++i) { if (Creature* pMatureBoneSifter = pCaster->SummonCreature(NPC_MATURE_BONE_SIFTER, pCreatureTarget->GetPositionX(), pCreatureTarget->GetPositionY(), pCreatureTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_OOC_DESPAWN, 30000)) pMatureBoneSifter->AI()->AttackStart(pCaster); } break; } } pCreatureTarget->ForcedDespawn(); } return true; } case SPELL_AHUNAES_KNIFE: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() != TYPEID_PLAYER) return true; ((Player*)pCaster)->KilledMonsterCredit(NPC_SCALPS_KILL_CREDIT_BUNNY); pCreatureTarget->ForcedDespawn(); return true; } return true; } case SPELL_TAILS_UP_GENDER_MASTER: { if (uiEffIndex == EFFECT_INDEX_0) { bool isMale = urand(0, 1); Player* pPlayer = pCreatureTarget->GetLootRecipient(); if (isMale) DoScriptText(SAY_ITS_MALE, pCreatureTarget, pPlayer); else DoScriptText(SAY_ITS_FEMALE, pCreatureTarget, pPlayer); switch (pCreatureTarget->GetEntry()) { case NPC_FROST_LEOPARD: { if (isMale) pCreatureTarget->CastSpell(pCreatureTarget, SPELL_TAILS_UP_AURA, true); else { pPlayer->KilledMonsterCredit(NPC_LEOPARD_KILL_CREDIT, pCreatureTarget->GetObjectGuid()); pCreatureTarget->CastSpell(pPlayer, SPELL_FORCE_LEOPARD_SUMMON, true); pCreatureTarget->ForcedDespawn(); } break; } case NPC_ICEPAW_BEAR: { if (isMale) pCreatureTarget->CastSpell(pCreatureTarget, SPELL_TAILS_UP_AURA, true); else { pPlayer->KilledMonsterCredit(NPC_BEAR_KILL_CREDIT, pCreatureTarget->GetObjectGuid()); pCreatureTarget->CastSpell(pPlayer, SPELL_FORCE_BEAR_SUMMON, true); pCreatureTarget->ForcedDespawn(); } break; } } return true; } return true; } case SPELL_THROW_GORDAWG_BOULDER: { if (uiEffIndex == EFFECT_INDEX_0) { for (int i = 0; i < 3; ++i) { if (irand(i, 2)) // 2-3 summons pCreatureTarget->SummonCreature(NPC_MINION_OF_GUROK, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 5000); } if (pCreatureTarget->getVictim()) { pCaster->DealDamage(pCreatureTarget, pCreatureTarget->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); return true; } // If not in combat, no xp or loot pCreatureTarget->SetDeathState(JUST_DIED); pCreatureTarget->SetHealth(0); return true; } return true; } case SPELL_HIT_APPLE: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() == TYPEID_PLAYER) ((Player*)pCaster)->KilledMonsterCredit(pCreatureTarget->GetEntry(), pCreatureTarget->GetObjectGuid()); pCreatureTarget->CastSpell(pCreatureTarget, SPELL_APPLE_FALLS_TO_GROUND, false); if (Creature* pLuckyWilhelm = GetClosestCreatureWithEntry(pCreatureTarget, NPC_LUCKY_WILHELM, 2 * INTERACTION_DISTANCE)) DoScriptText(SAY_LUCKY_HIT_APPLE, pLuckyWilhelm); } return true; } case SPELL_MISS_APPLE: { if (uiEffIndex == EFFECT_INDEX_0) { switch (urand(1, 3)) { case 1: DoScriptText(SAY_LUCKY_HIT_1, pCreatureTarget); break; case 2: DoScriptText(SAY_LUCKY_HIT_2, pCreatureTarget); break; case 3: DoScriptText(SAY_LUCKY_HIT_3, pCreatureTarget); break; } if (Creature* pDrostan = GetClosestCreatureWithEntry(pCreatureTarget, NPC_DROSTAN, 4 * INTERACTION_DISTANCE)) DoScriptText(urand(0, 1) ? SAY_DROSTAN_GOT_LUCKY_1 : SAY_DROSTAN_GOT_LUCKY_2, pDrostan); } return true; } case SPELL_MISS_APPLE_HIT_BIRD: { if (uiEffIndex == EFFECT_INDEX_0) { if (Creature* pDrostan = GetClosestCreatureWithEntry(pCreatureTarget, NPC_DROSTAN, 5 * INTERACTION_DISTANCE)) DoScriptText(urand(0, 1) ? SAY_DROSTAN_HIT_BIRD_1 : SAY_DROSTAN_HIT_BIRD_2, pDrostan); pCreatureTarget->DealDamage(pCreatureTarget, pCreatureTarget->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } return true; } case SPELL_LURIELLES_PENDANT: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->GetEntry() != NPC_CHILL_NYMPH || pCaster->GetTypeId() != TYPEID_PLAYER) return true; switch (urand(0, 2)) { case 0: DoScriptText(SAY_FREE_1, pCreatureTarget); break; case 1: DoScriptText(SAY_FREE_2, pCreatureTarget); break; case 2: DoScriptText(SAY_FREE_3, pCreatureTarget); break; } ((Player*)pCaster)->KilledMonsterCredit(NPC_LURIELLE); pCreatureTarget->SetFactionTemporary(FACTION_FRIENDLY, TEMPFACTION_RESTORE_RESPAWN); pCreatureTarget->DeleteThreatList(); pCreatureTarget->AttackStop(true); pCreatureTarget->GetMotionMaster()->MoveFleeing(pCaster, 7); pCreatureTarget->ForcedDespawn(7 * IN_MILLISECONDS); } return true; } case SPELL_SAMPLING_ENERGY: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() != TYPEID_PLAYER) return true; ((Player*)pCaster)->KilledMonsterCredit(pCreatureTarget->GetEntry()); } return true; } case SPELL_EXPOSE_RAZORTHORN_ROOT: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->GetEntry() != NPC_RAZORTHORN_RAVAGER) return true; if (GameObject* pMound = GetClosestGameObjectWithEntry(pCreatureTarget, GO_RAZORTHORN_DIRT_MOUND, 20.0f)) { if (pMound->GetRespawnTime() != 0) return true; pCreatureTarget->CastSpell(pCreatureTarget, SPELL_SUMMON_RAZORTHORN_ROOT, true); pMound->SetLootState(GO_JUST_DEACTIVATED); } } return true; } case SPELL_MELODIOUS_RAPTURE: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() != TYPEID_PLAYER && pCreatureTarget->GetEntry() != NPC_DEEPRUN_RAT) return true; pCreatureTarget->UpdateEntry(NPC_ENTHRALLED_DEEPRUN_RAT); pCreatureTarget->CastSpell(pCreatureTarget, SPELL_MELODIOUS_RAPTURE_VISUAL, false); pCreatureTarget->GetMotionMaster()->MoveFollow(pCaster, frand(0.5f, 3.0f), frand(M_PI_F * 0.8f, M_PI_F * 1.2f)); ((Player*)pCaster)->KilledMonsterCredit(NPC_ENTHRALLED_DEEPRUN_RAT); } return true; } } return false; }
SpellEntry const* ScriptedAI::SelectSpell(Unit* pTarget, int32 uiSchool, int32 uiMechanic, SelectTargetType selectTargets, uint32 uiPowerCostMin, uint32 uiPowerCostMax, float fRangeMin, float fRangeMax, SelectEffect selectEffects) { //No target so we can't cast if (!pTarget) return false; //Silenced so we can't cast if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) return false; //Using the extended script system we first create a list of viable spells SpellEntry const* apSpell[CREATURE_MAX_SPELLS]; memset(apSpell, 0, sizeof(SpellEntry*)*CREATURE_MAX_SPELLS); uint32 uiSpellCount = 0; SpellEntry const* pTempSpell; SpellRangeEntry const* pTempRange; //Check if each spell is viable(set it to null if not) for (uint32 i = 0; i < CREATURE_MAX_SPELLS; i++) { pTempSpell = GetSpellStore()->LookupEntry(m_creature->m_spells[i]); //This spell doesn't exist if (!pTempSpell) continue; // Targets and Effects checked first as most used restrictions //Check the spell targets if specified if (selectTargets && !(SpellSummary[m_creature->m_spells[i]].Targets & (1 << (selectTargets-1)))) continue; //Check the type of spell if we are looking for a specific spell type if (selectEffects && !(SpellSummary[m_creature->m_spells[i]].Effects & (1 << (selectEffects-1)))) continue; //Check for school if specified if (uiSchool >= 0 && pTempSpell->SchoolMask & uiSchool) continue; //Check for spell mechanic if specified if (uiMechanic >= 0 && pTempSpell->Mechanic != uiMechanic) continue; //Make sure that the spell uses the requested amount of power if (uiPowerCostMin && pTempSpell->manaCost < uiPowerCostMin) continue; if (uiPowerCostMax && pTempSpell->manaCost > uiPowerCostMax) continue; //Continue if we don't have the mana to actually cast this spell if (pTempSpell->manaCost > m_creature->GetPower((Powers)pTempSpell->powerType)) continue; //Get the Range pTempRange = GetSpellRangeStore()->LookupEntry(pTempSpell->rangeIndex); //Spell has invalid range store so we can't use it if (!pTempRange) continue; //Check if the spell meets our range requirements if (fRangeMin && m_creature->GetSpellMinRangeForTarget(pTarget, pTempRange) < fRangeMin) continue; if (fRangeMax && m_creature->GetSpellMaxRangeForTarget(pTarget, pTempRange) > fRangeMax) continue; //Check if our target is in range if (m_creature->IsWithinDistInMap(pTarget, m_creature->GetSpellMinRangeForTarget(pTarget, pTempRange)) || !m_creature->IsWithinDistInMap(pTarget, m_creature->GetSpellMaxRangeForTarget(pTarget, pTempRange))) continue; //All good so lets add it to the spell list apSpell[uiSpellCount] = pTempSpell; ++uiSpellCount; } //We got our usable spells so now lets randomly pick one if (!uiSpellCount) return NULL; return apSpell[rand()%uiSpellCount]; }
void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if(m_uiDoorTimer < uiDiff && !bIsDoorClosed) { if (GameObject* pForceBarrier = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(DATA_GO_FORCEFIELD))) pForceBarrier->SetGoState(GO_STATE_READY); if (GameObject* pWallA = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(DATA_KALECGOS_FIGHT_GATE_A))) pWallA->SetGoState(GO_STATE_READY); if (GameObject* pWallB = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(DATA_KALECGOS_FIGHT_GATE_B))) pWallB->SetGoState(GO_STATE_READY); bIsDoorClosed = true; }m_uiDoorTimer -= uiDiff; if (m_creature->HasAura(SPELL_BANISH)) { if (m_pInstance && m_pInstance->GetData(DATA_SATHROVARR_EVENT) == DONE) m_creature->RemoveAurasDueToSpell(SPELL_BANISH); if (m_pInstance && m_pInstance->GetData(DATA_KALECGOS_EVENT) == NOT_STARTED) { m_creature->RemoveAurasDueToSpell(SPELL_BANISH); ((boss_kalecgosAI*)m_creature->AI())->Reset(); m_creature->AI()->EnterEvadeMode(); } return; } /* Banish at 1% hp working */ if (!bBanished && (m_creature->GetHealthPercent() < 1.0f)) { if (m_pInstance) m_pInstance->SetData(DATA_KALECGOS_EVENT, DONE); DoCast(m_creature, SPELL_BANISH, true); bBanished = true; } //Mising VMAPS workarroud, ANTY BUG :D if (Unit* pSpectral = m_creature->GetMap()->GetUnit(m_uiNormalGUID)) if (m_creature->GetHealthPercent() > 1.0f) if (!m_creature->IsInRange(pSpectral, 0.0f, 50.0f, true)) { m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), DRAGON_REALM_Z, m_creature->GetOrientation()); ((boss_kalecgosAI*)m_creature->AI())->Reset(); m_creature->AI()->EnterEvadeMode(); } Unit* pWho = m_creature->getVictim(); if(pWho && !pWho->IsInRange(m_creature, 0.0f, 50.0f, true)) { m_creature->AddThreat(pWho, -100000.0f); if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) { m_creature->AddThreat(pTarget, 100000.0f); m_creature->AI()->AttackStart(pTarget); } } //END //Enrage at 10% both bosses if (!bEnraged) { if (m_pInstance && m_pInstance->GetData(DATA_SATHROVARR_EVENT) == SPECIAL) { if (Unit* pSathrovarr = m_creature->GetMap()->GetUnit(m_pInstance->GetData64(DATA_SATHROVARR))) { if (pSathrovarr->isAlive()) pSathrovarr->CastSpell(pSathrovarr, SPELL_CRAZED_RAGE, true); } m_uiNextEnrageTimer = 10000; bEnraged = true; } if (m_creature->GetHealthPercent() < 10.0f) { if (m_pInstance) m_pInstance->SetData(DATA_SATHROVARR_EVENT,SPECIAL); DoCast(m_creature, SPELL_CRAZED_RAGE, true); m_uiNextEnrageTimer = 10000; bEnraged = true; } } else if (m_uiNextEnrageTimer < uiDiff) { DoCast(m_creature, SPELL_CRAZED_RAGE, true); m_uiNextEnrageTimer = 10000; }else m_uiNextEnrageTimer -= uiDiff; //Simple Spelss if (m_uiArcaneBuffetTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_ARCANE_BUFFET) == CAST_OK) { m_uiArcaneBuffetTimer = 20000; } } else m_uiArcaneBuffetTimer -= uiDiff; if (m_uiFrostBreathTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_FROST_BREATH) == CAST_OK) { if (!urand(0, 1)) DoScriptText(SAY_EVIL_SPELL2, m_creature); m_uiFrostBreathTimer = 25000; } } else m_uiFrostBreathTimer -= uiDiff; if (m_uiTailLashTimer < uiDiff) { if (m_creature->getVictim()) DoCast(m_creature->getVictim(), SPELL_TAIL_LASH); m_uiTailLashTimer = urand(25000, 40000); }else m_uiTailLashTimer -= uiDiff; if (m_uiWildMagicTimer < uiDiff) { CastWildMagic(); }else m_uiWildMagicTimer -= uiDiff; //end of simple spells DoMeleeAttackIfReady(); //Teleport To Spectral Realm if (m_uiSpectralBlastTimer < uiDiff) { ThreatList const& m_threatlist = m_creature->getThreatManager().getThreatList(); if (m_threatlist.empty()) { m_uiSpectralBlastTimer = 1000; return; } std::list<Unit*> targetList; for(ThreatList::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr) if((*itr)->getTarget() && (*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER && (*itr)->getTarget()->GetGUID() && !(*itr)->getTarget()->HasAura(SPELL_SPECTRAL_EXHAUSTION) && (*itr)->getTarget()->IsInRange(m_creature, 0.0f, 50.0f, true)) targetList.push_back((*itr)->getTarget()); if(targetList.empty()) { m_uiSpectralBlastTimer = 1000; return; } std::list<Unit*>::iterator i = targetList.begin(); advance(i, rand()%targetList.size()); if((*i)) { if(m_pInstance && m_pInstance->GetData(DATA_KALECGOS_EVENT) == SPECIAL) { m_uiSpectralBlastTimer = urand(20000, 25000); } else { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) if ( pTarget == (*i)) return; m_creature->AddThreat((*i), -100000.0f); (*i)->InterruptNonMeleeSpells(true); SpellEntry* pTempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_SPECTRAL_BLAST); if (pTempSpell) { pTempSpell->Effect[EFFECT_INDEX_2] = 0; (*i)->CastSpell((*i), pTempSpell, true); } (*i)->CastSpell((*i), SPELL_SPECTRAL_EXHAUSTION,true); ((Player*)(*i))->TeleportTo((*i)->GetMapId(), (*i)->GetPositionX(), (*i)->GetPositionY(), DEMON_REALM_Z, (*i)->GetOrientation()); } m_uiSpectralBlastTimer = urand(20000, 25000); }else m_uiSpectralBlastTimer = 1000; }else m_uiSpectralBlastTimer -= uiDiff; if (m_uiSathrovarrTimer < uiDiff && !bSathrospawnd) { if (m_pInstance) if (Creature* pSath = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_SATHROVARR))) { pSath->SetVisibility(VISIBILITY_ON); pSath->setFaction(14); bSathrospawnd = true; if(pSath->AI()) pSath->AI()->AttackStart(m_creature->getVictim()); } }else m_uiSathrovarrTimer -= uiDiff; }
void PlayerbotShamanAI::LoadSpells() { PlayerbotAI *ai = GetAI(); if (!ai) return; #pragma region SpellId Fill //totems HEALING_STREAM_TOTEM = ai->getSpellIdExact("Healing Stream Totem"); MANA_SPRING_TOTEM = ai->getSpellIdExact("Mana Spring Totem"); MANA_TIDE_TOTEM = ai->getSpellIdExact("Mana Tide Totem"); CLEANSING_TOTEM = ai->getSpellIdExact("Cleansing Totem"); FIRE_RESISTANCE_TOTEM = ai->getSpellIdExact("Fire Resistance Totem"); WINDFURY_TOTEM = ai->getSpellIdExact("Windfury Totem"); WRATH_OF_AIR_TOTEM = ai->getSpellIdExact("Wrath of Air Totem"); GROUNDING_TOTEM = ai->getSpellIdExact("Grounding Totem"); NATURE_RESISTANCE_TOTEM = ai->getSpellIdExact("Nature Resistance Totem"); STRENGTH_OF_EARTH_TOTEM = ai->getSpellIdExact("Strength of Earth Totem"); EARTHBIND_TOTEM = ai->getSpellIdExact("Earthbind Totem"); STONESKIN_TOTEM = ai->getSpellIdExact("Stoneskin Totem"); STONECLAW_TOTEM = ai->getSpellIdExact("Stoneclaw Totem"); TREMOR_TOTEM = ai->getSpellIdExact("Tremor Totem"); EARTH_ELEMENTAL_TOTEM = ai->getSpellIdExact("Earth Elemental Totem"); FLAMETONGUE_TOTEM = ai->getSpellIdExact("Flametongue Totem"); TOTEM_OF_WRATH = ai->getSpellIdExact("Totem of Wrath"); SEARING_TOTEM = ai->getSpellIdExact("Searing Totem"); MAGMA_TOTEM = ai->getSpellIdExact("Magma Totem"); FIRE_ELEMENTAL_TOTEM = ai->getSpellIdExact("Fire Elemental Totem"); FROST_RESISTANCE_TOTEM = ai->getSpellIdExact("Frost Resistance Totem"); TOTEMIC_RECALL = ai->getSpellIdExact("Totemic Recall"); CALL_OF_THE_ELEMENTS = ai->getSpellIdExact("Call of the Elements"); CALL_OF_THE_ANCESTORS = ai->getSpellIdExact("Call of the Ancestors"); CALL_OF_THE_SPIRITS = ai->getSpellIdExact("Call of the Spirits"); //restoration HEAL = ai->getSpellIdExact("Healing Wave"); LESSER_HEAL = ai->getSpellIdExact("Lesser Healing Wave"); CHAIN_HEAL = ai->getSpellIdExact("Chain Heal"); RIPTIDE = ai->getSpellIdExact("Riptide"); ANCESTRAL_SPIRIT = ai->getSpellIdExact("Ancestral Spirit"); CLEANSE_SPIRIT = ai->getSpellIdExact("Cleanse Spirit"); if (CLEANSE_SPIRIT) CLEANSE_SPIRIT = ai->getSpellIdExact("Cure Toxins"); //offensive spells LIGHTNING_BOLT = ai->getSpellIdExact("Lightning Bolt"); CHAIN_LIGHTNING = ai->getSpellIdExact("Chain Lightning"); FIRE_NOVA = ai->getSpellIdExact("Fire Nova"); THUNDERSTORM = ai->getSpellIdExact("Thunderstorm"); LAVA_BURST = ai->getSpellIdExact("Lava Burst"); EARTH_SHOCK = ai->getSpellIdExact("Earth Shock"); WIND_SHEAR = ai->getSpellIdExact("Wind Shear"); FLAME_SHOCK = ai->getSpellIdExact("Flame Shock"); FROST_SHOCK = ai->getSpellIdExact("Frost Shock"); PURGE = ai->getSpellIdExact("Purge"); HEX = ai->getSpellIdExact("Hex"); //buffs LIGHTNING_SHIELD = ai->getSpellIdExact("Lightning Shield"); WATER_SHIELD = ai->getSpellIdExact("Water Shield"); EARTH_SHIELD = ai->getSpellIdExact("Earth Shield"); HEROISM = ai->getSpellIdExact("Heroism"); if (HEROISM) HEROISM = ai->getSpellIdExact("Bloodlust"); ELEMENTAL_MASTERY = ai->getSpellIdExact("Elemental Mastery"); NATURES_SWIFTNESS = ai->getSpellIdExact("Nature's Swiftness"); WINDFURY_WEAPON = ai->getSpellIdExact("Windfury Weapon"); FLAMETONGUE_WEAPON = ai->getSpellIdExact("Flametongue Weapon"); FROSTBRAND_WEAPON = ai->getSpellIdExact("Frostbrand Weapon"); ROCKBITER_WEAPON = ai->getSpellIdExact("Rockbiter Weapon"); EARTHLIVING_WEAPON = ai->getSpellIdExact("Earthliving Weapon"); WATER_BREATHING = ai->getSpellIdExact("Water Breathing"); WATER_WALKING = ai->getSpellIdExact("Water Walking"); //melee LAVA_LASH = ai->getSpellIdExact("Lava Lash"); STORMSTRIKE = ai->getSpellIdExact("Stormstrike"); SHAMANISTIC_RAGE = ai->getSpellIdExact("Shamanistic Rage"); FERAL_SPIRIT = ai->getSpellIdExact("Feral Spirit"); GHOST_WOLF = ai->getSpellIdExact("Ghost Wolf"); EXHAUSTION = 57723; // heroism debuff SATED = 57724; // bloodlust debuff //MAELSTROM_WEAPON = 0; // We want the triggered aura, not the talent spell uint32 mwtrigger = ai->getSpellIdExact("Maelstrom Weapon",true); if (mwtrigger) { SpellEntry const *mwtSpell = GetSpellStore()->LookupEntry(mwtrigger); if (mwtSpell && mwtSpell->EffectTriggerSpell[0] > 0) MAELSTROM_WEAPON = mwtSpell->EffectTriggerSpell[0]; } TALENT_ELEMENTAL = ELEMENTAL_MASTERY; TALENT_ENHANCEMENT = STORMSTRIKE; TALENT_RESTO = EARTH_SHIELD; uint8 talentCounter = 0; if (TALENT_ELEMENTAL) talentCounter++; if (TALENT_ENHANCEMENT) talentCounter++; if (TALENT_RESTO) talentCounter++; //if (talentCounter > 1) { TALENT_ELEMENTAL = 0; TALENT_ENHANCEMENT = 0; TALENT_RESTO = 0; } //Unreliable Talent detection. #pragma endregion }
bool PlayerbotShamanAI::ChangeWeaponEnchants() { uint32 mhEnch = 0, ohEnch = 0; PlayerbotAI *ai = GetAI(); if(!ai) return false; Player *m_bot = GetPlayerBot(); if(!m_bot || m_bot->isDead()) return false; // Choose Weapon Enchant if (TALENT_RESTO) { mhEnch = EARTHLIVING_WEAPON; } else if (TALENT_ELEMENTAL){ mhEnch = FLAMETONGUE_WEAPON; } else { if (WINDFURY_WEAPON) { mhEnch = WINDFURY_WEAPON; if (m_bot->haveOffhandWeapon()) { if (LAVA_LASH) ohEnch = FLAMETONGUE_WEAPON; else ohEnch = WINDFURY_WEAPON; } } else if (FLAMETONGUE_WEAPON) { mhEnch = FLAMETONGUE_WEAPON; if (m_bot->haveOffhandWeapon()) ohEnch = FLAMETONGUE_WEAPON; } } Item* weap; uint32 enchant_id = 0; SpellEntry const *tSpell; bool castedsomething = false; if (mhEnch) { weap = m_bot->GetWeaponForAttack(BASE_ATTACK); if (weap) { tSpell = GetSpellStore()->LookupEntry(mhEnch); if (tSpell && tSpell->EffectMiscValue[0] > 0) { enchant_id = (uint32) tSpell->EffectMiscValue[0]; if (enchant_id && weap->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT) != enchant_id && sSpellItemEnchantmentStore.LookupEntry(enchant_id)) { m_bot->ApplyEnchantment(weap,TEMP_ENCHANTMENT_SLOT, false); //Remove old enchantment effect weap->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, 1800 * 1000, 0); //Add for 30 mins m_bot->ApplyEnchantment(weap, TEMP_ENCHANTMENT_SLOT, true); //Add new effect castedsomething = true; } } } } if (ohEnch) { weap = m_bot->GetWeaponForAttack(OFF_ATTACK); if (weap) { tSpell = GetSpellStore()->LookupEntry(ohEnch); if (tSpell && tSpell->EffectMiscValue[0] > 0) { enchant_id = (uint32) tSpell->EffectMiscValue[0]; if (enchant_id && weap->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT) != enchant_id && sSpellItemEnchantmentStore.LookupEntry(enchant_id)) { m_bot->ApplyEnchantment(weap,TEMP_ENCHANTMENT_SLOT, false); //Remove old enchantment effect weap->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, 1800 * 1000, 0); //Add for 30 mins m_bot->ApplyEnchantment(weap, TEMP_ENCHANTMENT_SLOT, true); //Add new effect castedsomething = true; } } } } return castedsomething; }
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; SpellAuraHolderPtr holder = pTarget->GetSpellAuraHolder(SpellID, pTarget->GetObjectGuid()); Aura* aura = NULL; if (!holder) { holder = CreateSpellAuraHolder(spell, pTarget, pTarget); addedToExisting = false; } if (aura = holder->GetAuraByEffectIndex(index)) { if (isStack) holder->ModStackAmount(1); } else { aura = holder->CreateAura(spell, index, &_basepoint, holder, pTarget, m_creature, NULL); holder->SetAuraDuration(aura->GetAuraMaxDuration()); } 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; };
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; };
CanCastResult BossSpellWorker::_BSWSpellSelector(uint8 m_uiSpellIdx, Unit* pTarget) { if (_bossSpellCount == 0) return CAST_FAIL_OTHER; SpellEntry const *spell; SpellTable* pSpell = &m_BossSpell[m_uiSpellIdx]; Unit* pSummon = NULL; debug_log("BSW: Casting spell number %u type %u",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget); switch (pSpell->m_CastTarget) { case DO_NOTHING: return CAST_OK; case CAST_ON_SELF: if (!pSpell->m_IsBugged) return _DoCastSpellIfCan(boss, pSpell->m_uiSpellEntry[currentDifficulty]); else return _BSWDoCast(m_uiSpellIdx, boss); break; case CAST_ON_SUMMONS: if (!pTarget) return CAST_FAIL_OTHER; else return _DoCastSpellIfCan(pTarget, pSpell->m_uiSpellEntry[currentDifficulty]); break; case CAST_ON_VICTIM: pTarget = boss->getVictim(); return _BSWCastOnTarget(pTarget, m_uiSpellIdx); break; case CAST_ON_RANDOM: pTarget = SelectUnit(SELECT_TARGET_RANDOM); return _BSWCastOnTarget(pTarget, m_uiSpellIdx); break; case CAST_ON_BOTTOMAGGRO: pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); return _BSWCastOnTarget(pTarget, m_uiSpellIdx); break; case CAST_ON_TARGET: return _BSWCastOnTarget(pTarget, m_uiSpellIdx); break; case APPLY_AURA_SELF: if (spell = (SpellEntry *)GetSpellStore()->LookupEntry(pSpell->m_uiSpellEntry[currentDifficulty])) if(boss->AddAura(pSpell->m_uiSpellEntry[currentDifficulty], boss)) return CAST_OK; else return CAST_FAIL_OTHER; break; case APPLY_AURA_TARGET: if (!pTarget) return CAST_FAIL_OTHER; if (spell = (SpellEntry *)GetSpellStore()->LookupEntry(pSpell->m_uiSpellEntry[currentDifficulty])) if (pTarget->AddAura(pSpell->m_uiSpellEntry[currentDifficulty], pTarget)) return CAST_OK; else return CAST_FAIL_OTHER; break; case SUMMON_NORMAL: pSummon = _doSummon(m_uiSpellIdx, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); if(pSummon) return CAST_OK; else return 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) return CAST_OK; else return CAST_FAIL_OTHER; break; case SUMMON_INSTANT: pSummon = _doSummon(m_uiSpellIdx, TEMPSUMMON_MANUAL_DESPAWN,0); if(pSummon) return CAST_OK; else return CAST_FAIL_OTHER; break; case CAST_ON_ALLPLAYERS: { CanCastResult res1 = CAST_FAIL_OTHER; 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(boss, pSpell->LocData.x)) if (!pSpell->m_IsBugged) { res1 = _DoCastSpellIfCan(pTarget, pSpell->m_uiSpellEntry[currentDifficulty]); } else { _BSWDoCast(m_uiSpellIdx, pTarget); res1 = CAST_OK; }; return res1; } break; } case CAST_ON_FRENDLY: pTarget = SelectLowHPFriendly(); return _BSWCastOnTarget(pTarget, m_uiSpellIdx); break; case CAST_ON_FRENDLY_LOWHP: pTarget = SelectLowHPFriendly(); return _BSWCastOnTarget(pTarget, m_uiSpellIdx); break; default: return CAST_FAIL_OTHER; break; }; return CAST_FAIL_OTHER; };
bool PlayerbotClassAI::castSelfCCBreakers (uint32 castList[]) { uint32 dispelSpell = 0; Player *dTarget = GetPlayerBot(); /* dispelSpell = (uint32) R_ESCAPE_ARTIST; // this is script effect, Unit::AuraMap const& auras = dTarget->GetOwnedAuras(); for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); itr++) { Aura * aura = itr->second; AuraApplication * aurApp = aura->GetApplicationOfTarget(dTarget->GetGUID()); if (!aurApp) continue; if ( ( aura->GetSpellProto()->Mechanic == MECHANIC_SNARE ) || ( aura->GetSpellProto()->Mechanic == MECHANIC_ROOT ) ) { if(aura->GetSpellProto()->Dispel == DISPEL_MAGIC) { bool positive = aurApp->IsPositive() ? (!(aura->GetSpellProto()->AttributesEx & SPELL_ATTR0_UNK7)) : false; // do not remove positive auras if friendly target // negative auras if non-friendly target if(positive == dTarget->IsFriendlyTo(caster)) continue; } return castSpell(dispelSpell, dTarget); } } return false; */ // racial abilities /* if( GetPlayerBot()->getRace() == RACE_BLOODELF && !pTarget->HasAura( ARCANE_TORRENT,0 ) && castSpell( ARCANE_TORRENT,pTarget ) ) { //GetPlayerBot()->Say("Arcane Torrent!", LANG_UNIVERSAL); } else if( GetPlayerBot()->getRace() == RACE_HUMAN && (GetPlayerBot()->HasUnitState( UNIT_STAT_STUNNED ) || GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_FEAR ) || GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_DECREASE_SPEED ) || GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_CHARM )) && castSpell( EVERY_MAN_FOR_HIMSELF, GetPlayerBot() ) ) { //GetPlayerBot()->Say("EVERY MAN FOR HIMSELF!", LANG_UNIVERSAL); } else if( GetPlayerBot()->getRace() == RACE_UNDEAD_PLAYER && (GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_FEAR ) || GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_CHARM )) && castSpell( WILL_OF_THE_FORSAKEN, GetPlayerBot() ) ) { // GetPlayerBot()->Say("WILL OF THE FORSAKEN!", LANG_UNIVERSAL); } else if( GetPlayerBot()->getRace() == RACE_DWARF && GetPlayerBot()->HasAuraState( AURA_STATE_DEADLY_POISON ) && castSpell( STONEFORM, GetPlayerBot() ) ) { //GetPlayerBot()->Say("STONEFORM!", LANG_UNIVERSAL); } else if( GetPlayerBot()->getRace() == RACE_GNOME && (GetPlayerBot()->HasUnitState( UNIT_STAT_STUNNED ) || GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_DECREASE_SPEED )) && castSpell( ESCAPE_ARTIST, GetPlayerBot() ) ) { // GetPlayerBot()->Say("ESCAPE ARTIST!", LANG_UNIVERSAL); } */ for (uint8 j = 0; j < sizeof (castList); j++) { dispelSpell = castList[j]; if (dispelSpell == 0 || !dTarget->HasSpell(dispelSpell) || !CanCast(dispelSpell, dTarget, true)) continue; SpellEntry const *dSpell = GetSpellStore()->LookupEntry(dispelSpell); if (!dSpell) continue; for (uint8 i = 0 ; i < MAX_SPELL_EFFECTS ; ++i) { if (dSpell->Effect[i] != (uint32)SPELL_EFFECT_DISPEL && dSpell->Effect[i] != (uint32)SPELL_EFFECT_APPLY_AURA) continue; if (dSpell->Effect[i] == (uint32)SPELL_EFFECT_APPLY_AURA && ( (dSpell->EffectApplyAuraName[i] != (uint32) SPELL_AURA_MECHANIC_IMMUNITY) || (dSpell->EffectApplyAuraName[i] != (uint32) SPELL_AURA_DISPEL_IMMUNITY) )) continue; Unit::AuraMap const& auras = dTarget->GetOwnedAuras(); for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); itr++) { Aura * aura = itr->second; AuraApplication * aurApp = aura->GetApplicationOfTarget(dTarget->GetGUID()); if (!aurApp) continue; if (aura->GetSpellProto() && ( (dSpell->Effect[i] == (uint32)SPELL_EFFECT_DISPEL && ((1<<aura->GetSpellProto()->Dispel) & GetDispellMask(DispelType(dSpell->EffectMiscValue[i]))) ) || (dSpell->EffectApplyAuraName[i] == (uint32) SPELL_AURA_MECHANIC_IMMUNITY && ( GetAllSpellMechanicMask(aura->GetSpellProto()) & ( 1 << dSpell->EffectMiscValue[i]) ) ) || (dSpell->EffectApplyAuraName[i] == (uint32) SPELL_AURA_DISPEL_IMMUNITY && ( (1<<aura->GetSpellProto()->Dispel) & GetDispellMask(DispelType(dSpell->EffectMiscValue[i])) ) ) ) ) { if(aura->GetSpellProto()->Dispel == DISPEL_MAGIC) { bool positive = aurApp->IsPositive() ? (!(aura->GetSpellProto()->AttributesEx & SPELL_ATTR0_UNK7)) : false; if(positive)continue; } return CastSpell(dispelSpell, dTarget, false); } } } } return false; }
void ScriptMgr::FillSpellSummary() { SpellSummary = new TSpellSummary[GetSpellStore()->GetNumRows()]; SpellEntry const* pTempSpell; for (uint32 i = 0; i < GetSpellStore()->GetNumRows(); ++i) { SpellSummary[i].Effects = 0; SpellSummary[i].Targets = 0; pTempSpell = GetSpellStore()->LookupEntry(i); //This spell doesn't exist if (!pTempSpell) continue; for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) { //Spell targets self if (pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_CASTER) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SELF-1); //Spell targets a single enemy if (pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ENEMY || pTempSpell->EffectImplicitTargetA[j] == TARGET_DST_TARGET_ENEMY) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY-1); //Spell targets AoE at enemy if (pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_AREA_ENEMY_SRC || pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_AREA_ENEMY_DST || pTempSpell->EffectImplicitTargetA[j] == TARGET_SRC_CASTER || pTempSpell->EffectImplicitTargetA[j] == TARGET_DEST_DYNOBJ_ENEMY) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_ENEMY-1); //Spell targets an enemy if (pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ENEMY || pTempSpell->EffectImplicitTargetA[j] == TARGET_DST_TARGET_ENEMY || pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_AREA_ENEMY_SRC || pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_AREA_ENEMY_DST || pTempSpell->EffectImplicitTargetA[j] == TARGET_SRC_CASTER || pTempSpell->EffectImplicitTargetA[j] == TARGET_DEST_DYNOBJ_ENEMY) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_ENEMY-1); //Spell targets a single friend(or self) if (pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_CASTER || pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ALLY || pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_PARTY) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND-1); //Spell targets aoe friends if (pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_PARTY_CASTER || pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_PARTY_TARGET || pTempSpell->EffectImplicitTargetA[j] == TARGET_SRC_CASTER) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_FRIEND-1); //Spell targets any friend(or self) if (pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_CASTER || pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ALLY || pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_PARTY || pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_PARTY_CASTER || pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_PARTY_TARGET || pTempSpell->EffectImplicitTargetA[j] == TARGET_SRC_CASTER) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_FRIEND-1); //Make sure that this spell includes a damage effect if (pTempSpell->Effect[j] == SPELL_EFFECT_SCHOOL_DAMAGE || pTempSpell->Effect[j] == SPELL_EFFECT_INSTAKILL || pTempSpell->Effect[j] == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE || pTempSpell->Effect[j] == SPELL_EFFECT_HEALTH_LEECH) SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_DAMAGE-1); //Make sure that this spell includes a healing effect (or an apply aura with a periodic heal) if (pTempSpell->Effect[j] == SPELL_EFFECT_HEAL || pTempSpell->Effect[j] == SPELL_EFFECT_HEAL_MAX_HEALTH || pTempSpell->Effect[j] == SPELL_EFFECT_HEAL_MECHANICAL || (pTempSpell->Effect[j] == SPELL_EFFECT_APPLY_AURA && pTempSpell->EffectApplyAuraName[j] == 8)) SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_HEALING-1); //Make sure that this spell applies an aura if (pTempSpell->Effect[j] == SPELL_EFFECT_APPLY_AURA) SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_AURA-1); } } }
SpellEntry const* ScriptedAI::SelectSpell(Unit* target, int32 school, int32 mechanic, SelectTarget selectTargets, uint32 powerCostMin, uint32 powerCostMax, float rangeMin, float rangeMax, SelectEffect selectEffects) { // No target so we can't cast if (!target) return nullptr; // Silenced so we can't cast if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) return nullptr; // Using the extended script system we first create a list of viable spells SpellEntry const* spellInfos[4]; memset(spellInfos, 0, sizeof(SpellEntry*) * 4); uint32 spellCount = 0; SpellEntry const* tempSpellInfo; SpellRangeEntry const* tempRange; // Check if each spell is viable(set it to null if not) for (uint8 i = 0; i < 4; ++i) { tempSpellInfo = GetSpellStore()->LookupEntry<SpellEntry>(m_creature->m_spells[i]); // This spell doesn't exist if (!tempSpellInfo) continue; // Targets and Effects checked first as most used restrictions // Check the spell targets if specified if (selectTargets && !(SpellSummary[m_creature->m_spells[i]].Targets & (1 << (selectTargets - 1)))) continue; // Check the type of spell if we are looking for a specific spell type if (selectEffects && !(SpellSummary[m_creature->m_spells[i]].Effects & (1 << (selectEffects - 1)))) continue; // Check for school if specified if (school >= 0 && tempSpellInfo->SchoolMask & school) continue; // Check for spell mechanic if specified if (mechanic >= 0 && tempSpellInfo->Mechanic != (uint32)mechanic) continue; // Make sure that the spell uses the requested amount of power if (powerCostMin && tempSpellInfo->manaCost < powerCostMin) continue; if (powerCostMax && tempSpellInfo->manaCost > powerCostMax) continue; // Continue if we don't have the mana to actually cast this spell if (tempSpellInfo->manaCost > m_creature->GetPower((Powers)tempSpellInfo->powerType)) continue; // Get the Range tempRange = GetSpellRangeStore()->LookupEntry(tempSpellInfo->rangeIndex); // Spell has invalid range store so we can't use it if (!tempRange) continue; // Check if the spell meets our range requirements if (rangeMin && tempRange->maxRange < rangeMin) continue; if (rangeMax && tempRange->maxRange > rangeMax) continue; // Check if our target is in range if (m_creature->IsWithinDistInMap(target, tempRange->minRange) || !m_creature->IsWithinDistInMap(target, tempRange->maxRange)) continue; // All good so lets add it to the spell list spellInfos[spellCount] = tempSpellInfo; ++spellCount; } // We got our usable spells so now lets randomly pick one if (!spellCount) return nullptr; return spellInfos[urand(0, spellCount - 1)]; }