Example #1
0
bool ScriptedAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered)
{
    //No target so we can't cast
    if (!Target || !Spell)
        return false;

    //Silenced so we can't cast
    if (!Triggered && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
        return false;

    //Check for power
    if (!Triggered && m_creature->GetPower((Powers)Spell->powerType) < Spell->manaCost)
        return false;

    SpellRangeEntry const *TempRange = NULL;

    TempRange = GetSpellRangeStore()->LookupEntry(Spell->rangeIndex);

    //Spell has invalid range store so we can't use it
    if (!TempRange)
        return false;

    //Unit is out of range of this spell
    if (!m_creature->IsInRange(Target,TempRange->minRange,TempRange->maxRange))
        return false;

    return true;
}
bool ScriptedAI::CanCast(Unit* pTarget, SpellEntry const* pSpell, bool bTriggered)
{
    //No target so we can't cast
    if (!pTarget || !pSpell)
        return false;

    //Silenced so we can't cast
    if (!bTriggered && me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
        return false;

    //Check for power
    if (!bTriggered && me->GetPower((Powers)pSpell->powerType) < pSpell->manaCost)
        return false;

    SpellRangeEntry const* pTempRange = GetSpellRangeStore()->LookupEntry(pSpell->rangeIndex);

    //Spell has invalid range store so we can't use it
    if (!pTempRange)
        return false;

    //Unit is out of range of this spell
    if (me->IsInRange(pTarget, m_creature->GetSpellMinRangeForTarget(pTarget, pTempRange), m_creature->GetSpellMaxRangeForTarget(pTarget, pTempRange)))
        return false;

    return true;
}
Example #3
0
bool ScriptedAI::CanCast(Unit* target, SpellEntry const* spell, bool triggered /*= false*/)
{
    //No target so we can't cast
    if (!target || !spell)
        return false;

    //Silenced so we can't cast
    if (!triggered && me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
        return false;

    //Check for power
    if (!triggered && me->GetPower(Powers(spell->powerType)) < spell->manaCost)
        return false;

    SpellRangeEntry const* tempRange = GetSpellRangeStore()->LookupEntry(spell->rangeIndex);

    //Spell has invalid range store so we can't use it
    if (!tempRange)
        return false;

    //Unit is out of range of this spell
    if (me->IsInRange(target, float(me->GetSpellMinRangeForTarget(target, tempRange)), float(me->GetSpellMaxRangeForTarget(target, tempRange))))
        return false;

    return true;
}
Example #4
0
    bool IsEnemyPlayerInRangeForSpell(uint32 uiSpellId)
    {
        SpellEntry const* pSpell = GetSpellStore()->LookupEntry(uiSpellId);

        //if spell not valid
        if (!pSpell)
            return false;

        //spell known, so lookup using rangeIndex
        SpellRangeEntry const* pSpellRange = GetSpellRangeStore()->LookupEntry(pSpell->rangeIndex);

        //not valid, so return
        if (!pSpellRange)
            return false;

        ThreatList const& tList = m_creature->getThreatManager().getThreatList();
        for (ThreatList::const_iterator iter = tList.begin();iter != tList.end(); ++iter)
        {
            Unit* pTarget = Unit::GetUnit((*m_creature), (*iter)->getUnitGuid());

            if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER)
            {
                //if target further away than maxrange or closer than minrange, statement is false
                if (m_creature->IsInRange(pTarget, pSpellRange->minRange, pSpellRange->maxRange))
                    return true;
            }
        }

        return false;
    }
Example #5
0
float ScriptedAI::GetSpellMaxRange(uint32 id)
{
    SpellEntry const *spellInfo = GetSpellStore()->LookupEntry(id);
    if(!spellInfo)
        return 0;

    SpellRangeEntry const *range = GetSpellRangeStore()->LookupEntry(spellInfo->rangeIndex);
    if(!range)
        return 0;
    return range->maxRange;
}
CanCastResult BossSpellWorker::_CanCastSpell(Unit* pTarget, const SpellEntry *pSpell, bool isTriggered)
{
    if (!pTarget || !pTarget->IsInMap(boss) || !pTarget->isAlive()) return CAST_FAIL_OTHER;
    // If not triggered, we check
    if (!isTriggered)
    {
        // State does not allow
        if (boss->hasUnitState(UNIT_STAT_CAN_NOT_REACT))
            return CAST_FAIL_STATE;

        if (pSpell->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && boss->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
            return CAST_FAIL_STATE;

        if (pSpell->PreventionType == SPELL_PREVENTION_TYPE_PACIFY && boss->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED))
            return CAST_FAIL_STATE;

        // Check for power (also done by Spell::CheckCast())
        if (boss->GetPower((Powers)pSpell->powerType) < pSpell->manaCost)
            return CAST_FAIL_POWER;
    }

    if (const SpellRangeEntry *pSpellRange = GetSpellRangeStore()->LookupEntry(pSpell->rangeIndex))
    {
        if (pTarget != boss)
        {
        if (!pTarget->IsPositionValid() || !boss->IsPositionValid()) return CAST_FAIL_OTHER;

            // pTarget is out of range of this spell (also done by Spell::CheckCast())
            float fDistance = boss->GetCombatDistance(pTarget);

            if (fDistance > (boss->IsHostileTo(pTarget) ? pSpellRange->maxRange : pSpellRange->maxRangeFriendly))
                return CAST_FAIL_TOO_FAR;

            float fMinRange = boss->IsHostileTo(pTarget) ? pSpellRange->minRange : pSpellRange->minRangeFriendly;

            if (fMinRange && fDistance < fMinRange)
                return CAST_FAIL_TOO_CLOSE;
        }

        return CAST_OK;
    }
    else
        return CAST_FAIL_OTHER;
}
Example #7
0
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];
}
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];
}
Example #9
0
SpellEntry const* ScriptedAI::SelectSpell(Unit* target, uint32 school, uint32 mechanic, SelectTargetType 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 (me->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, CREATURE_MAX_SPELLS * sizeof(SpellEntry*));

    uint32 spellCount = 0;

    SpellEntry const* tempSpell = NULL;
    SpellRangeEntry const* tempRange = NULL;

    //Check if each spell is viable(set it to null if not)
    for (uint32 i = 0; i < CREATURE_MAX_SPELLS; i++)
    {
        tempSpell = sSpellStore.LookupEntry(me->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[me->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[me->m_spells[i]].Effects & (1 << (effects-1))))
            continue;

        //Check for school if specified
        if (school && (tempSpell->SchoolMask & school) == 0)
            continue;

        //Check for spell mechanic if specified
        if (mechanic && 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 > me->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 && me->GetSpellMinRangeForTarget(target, tempRange) < rangeMin)
            continue;
        if (rangeMax && me->GetSpellMaxRangeForTarget(target, tempRange) > rangeMax)
            continue;

        //Check if our target is in range
         if (me->IsWithinDistInMap(target, float(me->GetSpellMinRangeForTarget(target, tempRange))) || !me->IsWithinDistInMap(target, float(me->GetSpellMaxRangeForTarget(target, tempRange))))
            continue;

        //All good so lets add it to the spell list
        apSpell[spellCount] = tempSpell;
        ++spellCount;
    }

    //We got our usable spells so now lets randomly pick one
    if (!spellCount)
        return NULL;

    return apSpell[urand(0, spellCount - 1)];
}
Example #10
0
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;
};
Example #11
0
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)];
}
CanCastResult BossSpellWorker::_BSWSpellSelector(uint8 m_uiSpellIdx, Unit* pTarget)
{
    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 = boss->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
                   return _BSWCastOnTarget(pTarget, m_uiSpellIdx);
                   break;

            case CAST_ON_BOTTOMAGGRO:
                   pTarget = boss->SelectAttackingTarget(ATTACKING_TARGET_BOTTOMAGGRO,0);
                   return _BSWCastOnTarget(pTarget, m_uiSpellIdx);
                   break;

            case CAST_ON_TARGET:
                   return _BSWCastOnTarget(pTarget, m_uiSpellIdx);
                   break;

            case APPLY_AURA_SELF:
                   spell = (SpellEntry *)GetSpellStore()->LookupEntry(pSpell->m_uiSpellEntry[currentDifficulty]);
                   if (spell)
                       if (boss->AddAura(new BossAura(spell, EFFECT_INDEX_0, &pSpell->varData, boss, boss)))
                              return CAST_OK;
                   return CAST_FAIL_OTHER;
                   break;

            case APPLY_AURA_TARGET:
                   if (!pTarget || !pTarget->IsInMap(boss)) return CAST_FAIL_OTHER;
                       _doAura(m_uiSpellIdx, pTarget, EFFECT_INDEX_0);
                       return CAST_OK;
                   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(pSpell->LocData.x);
                   return _BSWCastOnTarget(pTarget, m_uiSpellIdx);
                   break;

            case CAST_ON_FRENDLY_LOWHP:
                   pTarget = SelectLowHPFriendly(pSpell->LocData.x);
                   return _BSWCastOnTarget(pTarget, m_uiSpellIdx);
                   break;

            case CAST_ON_RANDOM_POINT:
                   if (!pTarget) pTarget = boss;
                   if (pSpell->LocData.z <= 1.0f) {
                         float fPosX, fPosY, fPosZ;
                         if (!pTarget->IsPositionValid() || !pTarget->IsInMap(boss))
                            {
                                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]);
                                return CAST_FAIL_OTHER;
                            }
                         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");
                                    return CAST_FAIL_OTHER;
                                 }
                         if (SpellEntry const *spell = (SpellEntry *)GetSpellStore()->LookupEntry(pSpell->m_uiSpellEntry[currentDifficulty]))
                           if (SpellRangeEntry const *pSpellRange = GetSpellRangeStore()->LookupEntry(spell->rangeIndex))
                              if (boss->GetDistance(fPosX, fPosY, fPosZ) <= pSpellRange->maxRange)
                                 {
                                     boss->CastSpell(fPosX, fPosY, fPosZ, pSpell->m_uiSpellEntry[currentDifficulty], false);
                                     return CAST_OK;
                                 };
                                 return CAST_FAIL_TOO_FAR;
                         } else  return CAST_FAIL_OTHER;
                   break;

            case CAST_ON_RANDOM_PLAYER:
                   if ( pSpell->LocData.x < 1 ) pTarget = SelectRandomPlayer();
                       else pTarget = SelectRandomPlayerAtRange((float)pSpell->LocData.x);
                   if (pTarget && pTarget->IsInMap(boss)) return _BSWCastOnTarget(pTarget, m_uiSpellIdx);
                       else return CAST_FAIL_OTHER;
                   break;

            case APPLY_AURA_ALLPLAYERS:
                   {
                       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))
                               _doAura(m_uiSpellIdx, pTarget, EFFECT_INDEX_0);
                       }
                   return CAST_OK;
                   }
                   break;

            case SPELLTABLEPARM_NUMBER:
            default:
                   return CAST_FAIL_OTHER;
                   break;
            };

    error_log("BSW: FAILED casting spell number %u type %u - type not exists",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget);

    return CAST_FAIL_OTHER;
};