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; }
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; }
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; }
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; }
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]; }
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)]; }
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; };
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; };