diff options
Diffstat (limited to 'src/game/Spell.cpp')
-rw-r--r-- | src/game/Spell.cpp | 1040 |
1 files changed, 535 insertions, 505 deletions
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 3113beac3f6..8817854971e 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -75,7 +75,6 @@ SpellCastTargets::SpellCastTargets() m_itemTargetEntry = 0; m_srcX = m_srcY = m_srcZ = m_destX = m_destY = m_destZ = 0; - m_hasDest = false; m_strTarget = ""; m_targetMask = 0; } @@ -94,38 +93,49 @@ void SpellCastTargets::setUnitTarget(Unit *target) m_targetMask |= TARGET_FLAG_UNIT; } -void SpellCastTargets::setDestination(float x, float y, float z, bool send, int32 mapId) +void SpellCastTargets::setSrc(float x, float y, float z) +{ + m_srcX = x; + m_srcY = y; + m_srcZ = z; + m_targetMask |= TARGET_FLAG_SOURCE_LOCATION; +} + +void SpellCastTargets::setSrc(WorldObject *target) +{ + if(!target) + return; + + target->GetPosition(m_srcX, m_srcY, m_srcZ); + m_targetMask |= TARGET_FLAG_SOURCE_LOCATION; +} + +void SpellCastTargets::setDestination(float x, float y, float z, int32 mapId) { m_destX = x; m_destY = y; m_destZ = z; - m_hasDest = true; - if(send) - m_targetMask |= TARGET_FLAG_DEST_LOCATION; + m_targetMask |= TARGET_FLAG_DEST_LOCATION; if(mapId >= 0) m_mapId = mapId; } -void SpellCastTargets::setDestination(Unit *target, bool send) +void SpellCastTargets::setDestination(WorldObject *target) { if(!target) return; - m_destX = target->GetPositionX(); - m_destY = target->GetPositionY(); - m_destZ = target->GetPositionZ(); - m_hasDest = true; - if(send) - m_targetMask |= TARGET_FLAG_DEST_LOCATION; + target->GetPosition(m_destX, m_destY, m_destZ); + m_targetMask |= TARGET_FLAG_DEST_LOCATION; } -void SpellCastTargets::setSource(float x, float y, float z) +/*void SpellCastTargets::setSource(float x, float y, float z) { m_srcX = x; m_srcY = y; m_srcZ = z; m_targetMask |= TARGET_FLAG_SOURCE_LOCATION; -} +}*/ void SpellCastTargets::setGOTarget(GameObject *target) { @@ -211,8 +221,6 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster ) *data >> m_srcX >> m_srcY >> m_srcZ; if(!Trinity::IsValidMapCoord(m_srcX, m_srcY, m_srcZ)) return false; - - m_hasDest = true; } if( m_targetMask & TARGET_FLAG_DEST_LOCATION ) @@ -226,8 +234,6 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster ) *data >> m_destX >> m_destY >> m_destZ; if(!Trinity::IsValidMapCoord(m_destX, m_destY, m_destZ)) return false; - - m_hasDest = true; } if( m_targetMask & TARGET_FLAG_STRING ) @@ -435,28 +441,18 @@ void Spell::FillTargetMap() if(effectTargetType == SPELL_REQUIRE_NONE) continue; - std::list<Unit*> tmpUnitMap; uint32 targetA = m_spellInfo->EffectImplicitTargetA[i]; uint32 targetB = m_spellInfo->EffectImplicitTargetB[i]; if(targetA) - SetTargetMap(i, targetA, tmpUnitMap); + SetTargetMap(i, targetA); if(targetB) // In very rare case !A && B - SetTargetMap(i, targetB, tmpUnitMap); + SetTargetMap(i, targetB); if(effectTargetType != SPELL_REQUIRE_UNIT) { if(effectTargetType == SPELL_REQUIRE_CASTER) AddUnitTarget(m_caster, i); - /*else if(effectTargetType == SPELL_REQUIRE_DEST) - { - if(m_targets.HasDest() && m_spellInfo->speed > 0.0f) - { - float dist = m_caster->GetDistance(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ); - if (dist < 5.0f) dist = 5.0f; - m_delayMoment = (uint64) floor(dist / m_spellInfo->speed * 1000.0f); - } - }*/ else if(effectTargetType == SPELL_REQUIRE_ITEM) { if(m_targets.getItemTarget()) @@ -465,7 +461,7 @@ void Spell::FillTargetMap() continue; } - if(tmpUnitMap.empty() && m_spellInfo->Targets & TARGET_FLAG_CASTER) + if(/*tmpUnitMap.empty() && */m_spellInfo->Targets & TARGET_FLAG_CASTER) { AddUnitTarget(m_caster, i); continue; @@ -507,12 +503,12 @@ void Spell::FillTargetMap() { case TYPEID_UNIT: case TYPEID_PLAYER: - tmpUnitMap.push_back((Unit*)result); + AddUnitTarget((Unit*)result, i); break; case TYPEID_CORPSE: m_targets.setCorpseTarget((Corpse*)result); if(Player* owner = ObjectAccessor::FindPlayer(((Corpse*)result)->GetOwnerGUID())) - tmpUnitMap.push_back(owner); + AddUnitTarget(owner, i); break; } } @@ -536,7 +532,7 @@ void Spell::FillTargetMap() } default: if(m_targets.getUnitTarget()) - tmpUnitMap.push_back(m_targets.getUnitTarget()); + AddUnitTarget(m_targets.getUnitTarget(), i); break; } break; @@ -551,22 +547,22 @@ void Spell::FillTargetMap() case SPELL_EFFECT_REPUTATION: case SPELL_EFFECT_LEARN_SPELL: if(m_targets.getUnitTarget()) - tmpUnitMap.push_back(m_targets.getUnitTarget()); + AddUnitTarget(m_targets.getUnitTarget(), i); // Triggered spells have additional spell targets - cast them even if no explicit unit target is given (required for spell 50516 for example) else if(m_spellInfo->Effect[i] == SPELL_EFFECT_TRIGGER_SPELL) - tmpUnitMap.push_back(m_caster); + AddUnitTarget(m_caster, i); break; case SPELL_EFFECT_SUMMON_PLAYER: if(m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->GetSelection()) { Player* target = objmgr.GetPlayer(((Player*)m_caster)->GetSelection()); if(target) - tmpUnitMap.push_back(target); + AddUnitTarget(target, i); } break; case SPELL_EFFECT_RESURRECT_NEW: if(m_targets.getUnitTarget()) - tmpUnitMap.push_back(m_targets.getUnitTarget()); + AddUnitTarget(m_targets.getUnitTarget(), i); if(m_targets.getCorpseTargetGUID()) { Corpse *corpse = ObjectAccessor::GetCorpse(*m_caster,m_targets.getCorpseTargetGUID()); @@ -574,7 +570,7 @@ void Spell::FillTargetMap() { Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID()); if(owner) - tmpUnitMap.push_back(owner); + AddUnitTarget(owner, i); } } break; @@ -584,11 +580,11 @@ void Spell::FillTargetMap() case SPELL_EFFECT_STUCK: case SPELL_EFFECT_FEED_PET: case SPELL_EFFECT_DESTROY_ALL_TOTEMS: - tmpUnitMap.push_back(m_caster); + AddUnitTarget(m_caster, i); break; case SPELL_EFFECT_LEARN_PET_SPELL: if(Guardian* pet = m_caster->GetGuardianPet()) - tmpUnitMap.push_back(pet); + AddUnitTarget(pet, i); break; /*case SPELL_EFFECT_ENCHANT_ITEM: case SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY: @@ -602,9 +598,9 @@ void Spell::FillTargetMap() case SPELL_EFFECT_APPLY_AURA: switch(m_spellInfo->EffectApplyAuraName[i]) { - case SPELL_AURA_ADD_FLAT_MODIFIER: // some spell mods auras have 0 target modes instead expected TARGET_SELF(1) (and present for other ranks for same spell for example) + case SPELL_AURA_ADD_FLAT_MODIFIER: // some spell mods auras have 0 target modes instead expected TARGET_UNIT_CASTER(1) (and present for other ranks for same spell for example) case SPELL_AURA_ADD_PCT_MODIFIER: - tmpUnitMap.push_back(m_caster); + AddUnitTarget(m_caster, i); break; default: // apply to target in other case break; @@ -613,12 +609,12 @@ void Spell::FillTargetMap() case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: // AreaAura if(m_spellInfo->Attributes == 0x9050000 || m_spellInfo->Attributes == 0x10000) - SetTargetMap(i,TARGET_AREAEFFECT_PARTY,tmpUnitMap); + SetTargetMap(i, TARGET_UNIT_PARTY_TARGET); break; case SPELL_EFFECT_SKIN_PLAYER_CORPSE: if(m_targets.getUnitTarget()) { - tmpUnitMap.push_back(m_targets.getUnitTarget()); + AddUnitTarget(m_targets.getUnitTarget(), i); } else if (m_targets.getCorpseTargetGUID()) { @@ -627,7 +623,7 @@ void Spell::FillTargetMap() { Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID()); if(owner) - tmpUnitMap.push_back(owner); + AddUnitTarget(owner, i); } } break; @@ -636,27 +632,23 @@ void Spell::FillTargetMap() } } - if(IsChanneledSpell(m_spellInfo) && !tmpUnitMap.empty()) - m_needAliveTargetMask |= (1<<i); - - for (std::list<Unit*>::iterator itr = tmpUnitMap.begin() ; itr != tmpUnitMap.end();) + if(IsChanneledSpell(m_spellInfo)) { - if(!CheckTarget(*itr, i)) + uint8 mask = (1<<i); + for(std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { - itr = tmpUnitMap.erase(itr); - continue; + if(ihit->effectMask & mask) + { + m_needAliveTargetMask |= mask; + break; + } } - else - ++itr; } - - for(std::list<Unit*>::iterator iunit= tmpUnitMap.begin();iunit != tmpUnitMap.end();++iunit) - AddUnitTarget((*iunit), i); } if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) { - if(m_spellInfo->speed > 0.0f && m_targets.HasDest()) + if(m_spellInfo->speed > 0.0f && m_targets.HasDst()) { float dist = m_caster->GetDistance(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ); if (dist < 5.0f) dist = 5.0f; @@ -728,6 +720,9 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex) if( m_spellInfo->Effect[effIndex]==0 ) return; + if(!CheckTarget(pVictim, effIndex)) + return; + // Check for effect immune skip if immuned bool immuned = pVictim->IsImmunedToSpellEffect(m_spellInfo, effIndex); @@ -1375,13 +1370,13 @@ void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uin std::list<Unit*> tempUnitMap; if(TargetType == SPELL_TARGETS_CHAINHEAL) { - SearchAreaTarget(tempUnitMap, max_range, PUSH_TARGET_CENTER, SPELL_TARGETS_ALLY); + SearchAreaTarget(tempUnitMap, max_range, PUSH_CHAIN, SPELL_TARGETS_ALLY); tempUnitMap.sort(ChainHealingOrder(m_caster)); //if(cur->GetHealth() == cur->GetMaxHealth() && tempUnitMap.size()) // cur = tempUnitMap.front(); } else - SearchAreaTarget(tempUnitMap, max_range, PUSH_TARGET_CENTER, TargetType); + SearchAreaTarget(tempUnitMap, max_range, PUSH_CHAIN, TargetType); tempUnitMap.remove(cur); while(num) @@ -1431,34 +1426,38 @@ void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uin void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry) { float x, y, z; - if(type == PUSH_DEST_CENTER) - { - if(!m_targets.HasDest()) - { - sLog.outError( "SPELL: cannot find destination for spell ID %u\n", m_spellInfo->Id ); - return; - } - x = m_targets.m_destX; - y = m_targets.m_destY; - z = m_targets.m_destZ; - } - else if(type == PUSH_TARGET_CENTER) + switch(type) { - Unit *target = m_targets.getUnitTarget(); - if(!target) + case PUSH_DST_CENTER: + CheckDst(); + x = m_targets.m_destX; + y = m_targets.m_destY; + z = m_targets.m_destZ; + break; + case PUSH_SRC_CENTER: + CheckSrc(); + x = m_targets.m_srcX; + y = m_targets.m_srcY; + z = m_targets.m_srcZ; + break; + case PUSH_CHAIN: { - sLog.outError( "SPELL: cannot find unit target for spell ID %u\n", m_spellInfo->Id ); - return; + Unit *target = m_targets.getUnitTarget(); + if(!target) + { + sLog.outError( "SPELL: cannot find unit target for spell ID %u\n", m_spellInfo->Id ); + return; + } + x = target->GetPositionX(); + y = target->GetPositionY(); + z = target->GetPositionZ(); + break; } - x = target->GetPositionX(); - y = target->GetPositionY(); - z = target->GetPositionZ(); - } - else - { - x = m_caster->GetPositionX(); - y = m_caster->GetPositionY(); - z = m_caster->GetPositionZ(); + default: + x = m_caster->GetPositionX(); + y = m_caster->GetPositionY(); + z = m_caster->GetPositionZ(); + break; } Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, type, TargetType, entry, x, y, z); @@ -1469,83 +1468,112 @@ void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, SpellNo m_caster->GetMap()->VisitAll(x, y, radius, notifier); } -Unit* Spell::SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 entry) +WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType) { - Unit* target = NULL; switch(TargetType) { case SPELL_TARGETS_ENTRY: { - if(entry) + SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id); + SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); + if(lower == upper) { - Creature* target = NULL; - Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster, entry, true, radius); - Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(m_caster, target, u_check); - m_caster->VisitNearbyObject(radius, searcher); - return target; + sLog.outErrorDb("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry()); + if(IsPositiveSpell(m_spellInfo->Id)) + return SearchNearbyTarget(range, SPELL_TARGETS_ALLY); + else + return SearchNearbyTarget(range, SPELL_TARGETS_ENEMY); } - else + + Creature* creatureScriptTarget = NULL; + GameObject* goScriptTarget = NULL; + + for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST) { - //TODO: nearest player - return NULL; + switch(i_spellST->second.type) + { + case SPELL_TARGET_TYPE_GAMEOBJECT: + { + GameObject* p_GameObject = NULL; + + if(i_spellST->second.targetEntry) + { + Trinity::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster,i_spellST->second.targetEntry,range); + Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(m_caster,p_GameObject,go_check); + m_caster->VisitNearbyGridObject(range, checker); + + if(p_GameObject) + { + // remember found target and range, next attempt will find more near target with another entry + creatureScriptTarget = NULL; + goScriptTarget = p_GameObject; + range = go_check.GetLastRange(); + } + } + else if( focusObject ) //Focus Object + { + float frange = m_caster->GetDistance(focusObject); + if(range >= frange) + { + creatureScriptTarget = NULL; + goScriptTarget = focusObject; + range = frange; + } + } + break; + } + case SPELL_TARGET_TYPE_CREATURE: + case SPELL_TARGET_TYPE_DEAD: + default: + { + Creature *p_Creature = NULL; + + Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster,i_spellST->second.targetEntry,i_spellST->second.type!=SPELL_TARGET_TYPE_DEAD,range); + Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(m_caster,p_Creature, u_check); + m_caster->VisitNearbyObject(range, searcher); + + if(p_Creature ) + { + creatureScriptTarget = p_Creature; + goScriptTarget = NULL; + range = u_check.GetLastRange(); + } + break; + } + } } + + if(creatureScriptTarget) + return creatureScriptTarget; + else + return goScriptTarget; } default: case SPELL_TARGETS_ENEMY: { - Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius); + Unit *target = NULL; + Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, range); Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(m_caster, target, u_check); - m_caster->VisitNearbyObject(radius, searcher); - }break; + m_caster->VisitNearbyObject(range, searcher); + return target; + } case SPELL_TARGETS_ALLY: { - Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius); + Unit *target = NULL; + Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, range); Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(m_caster, target, u_check); - m_caster->VisitNearbyObject(radius, searcher); - }break; + m_caster->VisitNearbyObject(range, searcher); + return target; + } } - return target; } -void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) +void Spell::SetTargetMap(uint32 i, uint32 cur) { - float radius_h, radius_f; - if (m_spellInfo->EffectRadiusIndex[i]) - { - radius_h = GetSpellRadiusForHostile(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])) * m_spellValue->RadiusMod; - radius_f = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])) * m_spellValue->RadiusMod; - } - else - { - radius_h = GetSpellMaxRangeForHostile(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); - radius_f = GetSpellMaxRangeForFriend(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); - } - - //Chain: 2, 6, 22, 25, 45, 77 - uint32 EffectChainTarget = m_spellInfo->EffectChainTarget[i]; - uint32 unMaxTargets = m_spellValue->MaxAffectedTargets; - - Unit::AuraEffectList const& Auras = m_caster->GetAurasByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS); - for(Unit::AuraEffectList::const_iterator j = Auras.begin();j != Auras.end(); ++j) - { - if((*j)->isAffectedOnSpell(m_spellInfo)) - unMaxTargets+=(*j)->GetAmount(); - } - + SpellNotifyPushType pushType = PUSH_NONE; + Player *modOwner = NULL; if(m_originalCaster) - if (Player* modOwner = m_caster->GetSpellModOwner()) - { - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius_f,this); - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius_h,this); - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, EffectChainTarget, this); - } - - if(EffectChainTarget > 1) - { - //otherwise, this multiplier is used for something else - m_damageMultipliers[i] = 1.0f; - m_applyMultiplierMask |= 1 << i; - } + modOwner = m_originalCaster->GetSpellModOwner(); switch(spellmgr.SpellTargetType[cur]) { @@ -1555,361 +1583,135 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) { case TARGET_UNIT_CASTER: case TARGET_UNIT_CASTER_FISHING: - TagUnitMap.push_back(m_caster); + AddUnitTarget(m_caster, i); break; case TARGET_UNIT_MASTER: if(Unit* owner = m_caster->GetCharmerOrOwner()) - TagUnitMap.push_back(owner); + AddUnitTarget(owner, i); break; case TARGET_UNIT_PET: if(Guardian* pet = m_caster->GetGuardianPet()) - TagUnitMap.push_back(pet); + AddUnitTarget(pet, i); break; case TARGET_UNIT_PARTY_CASTER: - m_caster->GetPartyMember(TagUnitMap, radius_f); - break; - case TARGET_UNIT_RAID: - //if(Unit *target = m_targets.getUnitTarget()) - // TagUnitMap.push_back(target); - //else - m_caster->GetRaidMember(TagUnitMap, radius_f); + case TARGET_UNIT_RAID_CASTER: + pushType = PUSH_CASTER_CENTER; break; } - }break; + break; + } case TARGET_TYPE_UNIT_TARGET: { Unit *target = m_targets.getUnitTarget(); if(!target) { - sLog.outError("SPELL: no unit target for spell ID %u\n", m_spellInfo->Id); + sLog.outError("SPELL: no unit target for spell ID %u", m_spellInfo->Id); break; } - if(!IsPositiveSpell(m_spellInfo->Id)) - if(Unit *magnet = m_caster->SelectMagnetTarget(target)) - if(magnet != target) - m_targets.setUnitTarget(magnet); - switch(cur) { - case TARGET_UNIT_MINIPET: - if(target->GetGUID() == m_caster->m_SummonSlot[4]) - TagUnitMap.push_back(target); + case TARGET_UNIT_TARGET_ENEMY: + if(Unit *magnet = m_caster->SelectMagnetTarget(target)) + if(magnet != target) + m_targets.setUnitTarget(magnet); + pushType = PUSH_CHAIN; break; - case TARGET_UNIT_TARGET_ALLY: - case TARGET_UNIT_TARGET_RAID: case TARGET_UNIT_TARGET_ANY: - case TARGET_UNIT_TARGET_PARTY: - TagUnitMap.push_back(target); - break; - case TARGET_UNIT_PARTY_TARGET: - target->GetPartyMember(TagUnitMap, radius_f); - break; - case TARGET_UNIT_TARGET_ENEMY: - if(EffectChainTarget <= 1) - TagUnitMap.push_back(target); - else - SearchChainTarget(TagUnitMap, radius_h, EffectChainTarget, SPELL_TARGETS_ENEMY); + if(!IsPositiveSpell(m_spellInfo->Id)) + if(Unit *magnet = m_caster->SelectMagnetTarget(target)) + if(magnet != target) + m_targets.setUnitTarget(magnet); + pushType = PUSH_CHAIN; break; case TARGET_UNIT_CHAINHEAL: - if(EffectChainTarget <= 1) - TagUnitMap.push_back(target); - else - SearchChainTarget(TagUnitMap, radius_f, EffectChainTarget, SPELL_TARGETS_CHAINHEAL); + pushType = PUSH_CHAIN; break; - } - }break; - - case TARGET_TYPE_CHANNEL: - { - if(!m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]) - { - sLog.outError( "SPELL: no current channeled spell for spell ID %u\n", m_spellInfo->Id ); - break; - } - - switch(cur) - { - case TARGET_UNIT_CHANNEL: - if(Unit* target = m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets.getUnitTarget()) - TagUnitMap.push_back(target); - else - sLog.outError( "SPELL: cannot find channel spell target for spell ID %u\n", m_spellInfo->Id ); + case TARGET_UNIT_TARGET_ALLY: + case TARGET_UNIT_TARGET_RAID: + case TARGET_UNIT_TARGET_PARTY: + case TARGET_UNIT_MINIPET: + AddUnitTarget(target, i); break; - case TARGET_DEST_CHANNEL: - if(m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets.HasDest()) - m_targets = m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets; - else - sLog.outError( "SPELL: cannot find channel spell destination for spell ID %u\n", m_spellInfo->Id ); + case TARGET_UNIT_PARTY_TARGET: + case TARGET_UNIT_CLASS_TARGET: + pushType = PUSH_CASTER_CENTER; // not real break; } - }break; + break; + } - case TARGET_TYPE_AREA_DEST: + case TARGET_TYPE_UNIT_NEARBY: { - if(!m_targets.HasDest()) - { - sLog.outError( "SPELL: cannot find destination for spell ID %u\n", m_spellInfo->Id ); - return; - } - - // Dummy for client - if(spellmgr.EffectTargetType[m_spellInfo->Effect[i]] == SPELL_REQUIRE_DEST) - break; + WorldObject *target = NULL; + float range; switch(cur) { - case TARGET_UNIT_AREA_ENEMY_GROUND: - m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; - case TARGET_UNIT_AREA_ENEMY: - SearchAreaTarget(TagUnitMap, radius_h, PUSH_DEST_CENTER, SPELL_TARGETS_ENEMY); + case TARGET_UNIT_NEARBY_ENEMY: + range = GetSpellMaxRange(m_spellInfo, false); + if(modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); + target = SearchNearbyTarget(range, SPELL_TARGETS_ENEMY); break; - case TARGET_UNIT_AREA_ALLY_GROUND: - m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; - case TARGET_UNIT_AREA_ALLY: - SearchAreaTarget(TagUnitMap, radius_f, PUSH_DEST_CENTER, SPELL_TARGETS_ALLY); + case TARGET_UNIT_NEARBY_ALLY: + case TARGET_UNIT_NEARBY_ALLY_UNK: + case TARGET_UNIT_NEARBY_RAID: + range = GetSpellMaxRange(m_spellInfo, true); + if(modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); + target = SearchNearbyTarget(range, SPELL_TARGETS_ALLY); break; - case TARGET_UNIT_AREA_PARTY_GROUND: - m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; - case TARGET_UNIT_AREA_PARTY: - m_caster->GetPartyMember(TagUnitMap, radius_f); + case TARGET_UNIT_NEARBY_ENTRY: + range = GetSpellMaxRange(m_spellInfo, IsPositiveSpell(m_spellInfo->Id)); + if(modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); + target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY); break; - case TARGET_UNIT_AREA_ENTRY_GROUND: - m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; - case TARGET_UNIT_AREA_ENTRY: - { - SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id); - SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); - if(lower==upper) - { - SearchAreaTarget(TagUnitMap, radius_h, PUSH_DEST_CENTER, SPELL_TARGETS_ENEMY); - sLog.outErrorDb("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry()); - break; - } - // let it be done in one check? - for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST) - { - if(i_spellST->second.type != SPELL_TARGET_TYPE_CREATURE) - { - sLog.outError( "SPELL: spell ID %u requires non-creature target\n", m_spellInfo->Id ); - continue; - } - SearchAreaTarget(TagUnitMap, radius_f, PUSH_DEST_CENTER, SPELL_TARGETS_ENTRY, i_spellST->second.targetEntry); - } - } - break; } - }break; - case TARGET_TYPE_DEFAULT: - { - switch(cur) + if(!target) + return; + else if(target->GetTypeId() == TYPEID_UNIT) { + pushType = PUSH_CHAIN; - case TARGET_GAMEOBJECT: - { - if(m_targets.getGOTarget()) - AddGOTarget(m_targets.getGOTarget(), i); - }break; - case TARGET_GAMEOBJECT_ITEM: - { - if(m_targets.getGOTargetGUID()) - AddGOTarget(m_targets.getGOTarget(), i); - else if(m_targets.getItemTarget()) - AddItemTarget(m_targets.getItemTarget(), i); - }break; - - case TARGET_TABLE_X_Y_Z_COORDINATES: - if(SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id)) - { - //TODO: fix this check - if(m_spellInfo->Effect[0] == SPELL_EFFECT_TELEPORT_UNITS - || m_spellInfo->Effect[1] == SPELL_EFFECT_TELEPORT_UNITS - || m_spellInfo->Effect[2] == SPELL_EFFECT_TELEPORT_UNITS) - m_targets.setDestination(st->target_X, st->target_Y, st->target_Z, true, (int32)st->target_mapId); - else if(st->target_mapId == m_caster->GetMapId()) - m_targets.setDestination(st->target_X, st->target_Y, st->target_Z); + if(!m_targets.getUnitTarget()) + m_targets.setUnitTarget((Unit*)target); } - else - sLog.outError( "SPELL: unknown target coordinates for spell ID %u\n", m_spellInfo->Id ); - break; - case TARGET_INNKEEPER_COORDINATES: - if(m_caster->GetTypeId() == TYPEID_PLAYER) - m_targets.setDestination(((Player*)m_caster)->m_homebindX,((Player*)m_caster)->m_homebindY,((Player*)m_caster)->m_homebindZ, true, ((Player*)m_caster)->m_homebindMapId); - break; + else if(target->GetTypeId() == TYPEID_GAMEOBJECT) + AddGOTarget((GameObject*)target, i); - case TARGET_IN_FRONT_OF_CASTER: - case TARGET_UNIT_CONE_ENEMY_UNKNOWN: - if(m_customAttr & SPELL_ATTR_CU_CONE_BACK) - SearchAreaTarget(TagUnitMap, radius_h, PUSH_IN_BACK, SPELL_TARGETS_ENEMY); - else if(m_customAttr & SPELL_ATTR_CU_CONE_LINE) - SearchAreaTarget(TagUnitMap, radius_h, PUSH_IN_LINE, SPELL_TARGETS_ENEMY); - else - SearchAreaTarget(TagUnitMap, radius_h, PUSH_IN_FRONT, SPELL_TARGETS_ENEMY); - break; - case TARGET_UNIT_CONE_ALLY: - SearchAreaTarget(TagUnitMap, radius_f, PUSH_IN_FRONT, SPELL_TARGETS_ALLY); break; + } - // nearby target - case TARGET_UNIT_NEARBY_ALLY: - case TARGET_UNIT_NEARBY_ALLY_UNK: - if(!m_targets.getUnitTarget()) - m_targets.setUnitTarget(SearchNearbyTarget(radius_f, SPELL_TARGETS_ALLY)); - if(m_targets.getUnitTarget()) - { - if(EffectChainTarget <= 1) - TagUnitMap.push_back(m_targets.getUnitTarget()); - else - SearchChainTarget(TagUnitMap, radius_f, EffectChainTarget, SPELL_TARGETS_ALLY); - } + case TARGET_TYPE_AREA_SRC: + CheckSrc(); + pushType = PUSH_SRC_CENTER; break; - case TARGET_UNIT_NEARBY_ENEMY: - if(!m_targets.getUnitTarget()) - m_targets.setUnitTarget(SearchNearbyTarget(radius_h, SPELL_TARGETS_ENEMY)); - if(m_targets.getUnitTarget()) - { - if(EffectChainTarget <= 1) - TagUnitMap.push_back(m_targets.getUnitTarget()); - else - SearchChainTarget(TagUnitMap, radius_h, EffectChainTarget, SPELL_TARGETS_ENEMY); - } - break; - case TARGET_SCRIPT: - case TARGET_SCRIPT_COORDINATES: - case TARGET_UNIT_AREA_SCRIPT: - { - SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id); - SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); - if(lower==upper) - { - sLog.outErrorDb("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry()); - TagUnitMap.push_back(m_caster); - break; - } - - SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex); - float range = GetSpellMaxRangeForHostile(srange); - - Creature* creatureScriptTarget = NULL; - GameObject* goScriptTarget = NULL; - - for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST) - { - switch(i_spellST->second.type) - { - case SPELL_TARGET_TYPE_GAMEOBJECT: - { - GameObject* p_GameObject = NULL; - - if(i_spellST->second.targetEntry) - { - Trinity::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster,i_spellST->second.targetEntry,range); - Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(m_caster, p_GameObject,go_check); - m_caster->VisitNearbyGridObject(range, checker); - - if(p_GameObject) - { - // remember found target and range, next attempt will find more near target with another entry - creatureScriptTarget = NULL; - goScriptTarget = p_GameObject; - range = go_check.GetLastRange(); - } - } - else if( focusObject ) //Focus Object - { - float frange = m_caster->GetDistance(focusObject); - if(range >= frange) - { - creatureScriptTarget = NULL; - goScriptTarget = focusObject; - range = frange; - } - } - break; - } - case SPELL_TARGET_TYPE_CREATURE: - case SPELL_TARGET_TYPE_DEAD: - default: - { - Creature *p_Creature = NULL; - - Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster,i_spellST->second.targetEntry,i_spellST->second.type!=SPELL_TARGET_TYPE_DEAD,range); - Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(m_caster, p_Creature, u_check); - m_caster->VisitNearbyObject(range, searcher); - - if(p_Creature ) - { - creatureScriptTarget = p_Creature; - goScriptTarget = NULL; - range = u_check.GetLastRange(); - } - break; - } - } - } - - if(cur == TARGET_SCRIPT_COORDINATES) - { - if(creatureScriptTarget) - m_targets.setDestination(creatureScriptTarget->GetPositionX(),creatureScriptTarget->GetPositionY(),creatureScriptTarget->GetPositionZ()); - else if(goScriptTarget) - m_targets.setDestination(goScriptTarget->GetPositionX(),goScriptTarget->GetPositionY(),goScriptTarget->GetPositionZ()); - } - else - { - if(creatureScriptTarget) - TagUnitMap.push_back(creatureScriptTarget); - else if(goScriptTarget) - AddGOTarget(goScriptTarget, i); - } - }break; - // dummy - case TARGET_AREAEFFECT_CUSTOM_2: - { - TagUnitMap.push_back(m_caster); + case TARGET_TYPE_AREA_DST: + CheckDst(); + pushType = PUSH_DST_CENTER; break; - } - case TARGET_AREAEFFECT_PARTY_AND_CLASS: - { - Player* targetPlayer = m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER - ? (Player*)m_targets.getUnitTarget() : NULL; - - Group* pGroup = targetPlayer ? targetPlayer->GetGroup() : NULL; - if(pGroup) - { - for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* Target = itr->getSource(); - // IsHostileTo check duel and controlled by enemy - if( Target && targetPlayer->IsWithinDistInMap(Target, radius_f) && - targetPlayer->getClass() == Target->getClass() && - !m_caster->IsHostileTo(Target) ) - { - TagUnitMap.push_back(Target); - } - } - } - else if(m_targets.getUnitTarget()) - TagUnitMap.push_back(m_targets.getUnitTarget()); + case TARGET_TYPE_AREA_CONE: + if(m_customAttr & SPELL_ATTR_CU_CONE_BACK) + pushType = PUSH_IN_BACK; + else if(m_customAttr & SPELL_ATTR_CU_CONE_LINE) + pushType = PUSH_IN_LINE; + else + pushType = PUSH_IN_FRONT; break; - } - } - }break; - - case TARGET_TYPE_DEST_CASTER: + + case TARGET_TYPE_DEST_CASTER: //4+8+2 { - if(cur == TARGET_DEST_CASTER_GROUND) + if(cur == TARGET_SRC_CASTER) { - m_targets.setDestination(m_caster, true); + m_targets.setSrc(m_caster); break; } - else if(cur == TARGET_DEST_CASTER) + else if(cur == TARGET_DST_CASTER) { - m_targets.setDestination(m_caster, false); + m_targets.setDestination(m_caster); break; } @@ -1938,10 +1740,11 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) } m_caster->GetGroundPointAroundUnit(x, y, z, dist, angle); - m_targets.setDestination(x, y, z); // do not know if has ground visual - }break; + m_targets.setDestination(x, y, z); + break; + } - case TARGET_TYPE_DEST_TARGET: + case TARGET_TYPE_DEST_TARGET: //2+8+2 { Unit *target = m_targets.getUnitTarget(); if(!target) @@ -1950,9 +1753,9 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) break; } - if(cur == TARGET_DEST_TARGET_ENEMY || cur == TARGET_DEST_TARGET_ANY) + if(cur == TARGET_DST_TARGET_ENEMY || cur == TARGET_DEST_TARGET_ANY) { - m_targets.setDestination(target, true); + m_targets.setDestination(target); break; } @@ -1979,12 +1782,13 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) } target->GetGroundPointAroundUnit(x, y, z, dist, angle); - m_targets.setDestination(x, y, z); // do not know if has ground visual - }break; + m_targets.setDestination(x, y, z); + break; + } - case TARGET_TYPE_DEST_DEST: + case TARGET_TYPE_DEST_DEST: //5+8+1 { - if(!m_targets.HasDest()) + if(!m_targets.HasDst()) { sLog.outError("SPELL: no destination for spell ID %u\n", m_spellInfo->Id); break; @@ -1995,7 +1799,9 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) { case TARGET_DEST_DYNOBJ_ENEMY: case TARGET_DEST_DYNOBJ_ALLY: + case TARGET_DEST_DYNOBJ_NONE: case TARGET_DEST_DEST: + case TARGET_DEST_TRAJ: return; case TARGET_DEST_DEST_FRONT: angle = 0.0f; break; case TARGET_DEST_DEST_BACK: angle = M_PI; break; @@ -2017,45 +1823,269 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) y = m_targets.m_destY; z = m_targets.m_destZ; m_caster->GetGroundPoint(x, y, z, dist, angle); - m_targets.setDestination(x, y, z); // do not know if has ground visual - }break; + m_targets.setDestination(x, y, z); + break; + } + + case TARGET_TYPE_DEST_SPECIAL: + { + switch(cur) + { + case TARGET_DST_DB: + if(SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id)) + { + //TODO: fix this check + if(m_spellInfo->Effect[0] == SPELL_EFFECT_TELEPORT_UNITS + || m_spellInfo->Effect[1] == SPELL_EFFECT_TELEPORT_UNITS + || m_spellInfo->Effect[2] == SPELL_EFFECT_TELEPORT_UNITS) + m_targets.setDestination(st->target_X, st->target_Y, st->target_Z, (int32)st->target_mapId); + else if(st->target_mapId == m_caster->GetMapId()) + m_targets.setDestination(st->target_X, st->target_Y, st->target_Z); + } + else + sLog.outError( "SPELL: unknown target coordinates for spell ID %u\n", m_spellInfo->Id ); + break; + case TARGET_DST_HOME: + if(m_caster->GetTypeId() == TYPEID_PLAYER) + m_targets.setDestination(((Player*)m_caster)->m_homebindX,((Player*)m_caster)->m_homebindY,((Player*)m_caster)->m_homebindZ, ((Player*)m_caster)->m_homebindMapId); + break; + case TARGET_DST_NEARBY_ENTRY: + { + float range = GetSpellMaxRange(m_spellInfo, IsPositiveSpell(m_spellInfo->Id)); + if(modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); + + WorldObject *target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY); + if(target) + m_targets.setDestination(target); + break; + } + } + break; + } + + case TARGET_TYPE_CHANNEL: + { + if(!m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]) + { + sLog.outError( "SPELL: no current channeled spell for spell ID %u", m_spellInfo->Id ); + break; + } + + switch(cur) + { + case TARGET_UNIT_CHANNEL: + if(Unit* target = m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets.getUnitTarget()) + AddUnitTarget(target, i); + else + sLog.outError( "SPELL: cannot find channel spell target for spell ID %u", m_spellInfo->Id ); + break; + case TARGET_DEST_CHANNEL: + if(m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets.HasDst()) + m_targets = m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets; + else + sLog.outError( "SPELL: cannot find channel spell destination for spell ID %u", m_spellInfo->Id ); + break; + } + break; + } default: + { + switch(cur) + { + case TARGET_GAMEOBJECT: + case TARGET_OBJECT_USE: + if(m_targets.getGOTarget()) + AddGOTarget(m_targets.getGOTarget(), i); + break; + case TARGET_GAMEOBJECT_ITEM: + if(m_targets.getGOTargetGUID()) + AddGOTarget(m_targets.getGOTarget(), i); + else if(m_targets.getItemTarget()) + AddItemTarget(m_targets.getItemTarget(), i); + break; + default: + sLog.outError("Unhandled spell target %u", cur); + break; + } break; + } } - if(unMaxTargets && !EffectChainTarget && TagUnitMap.size() > 1) + if(pushType == PUSH_CHAIN) // Chain { - if(m_spellInfo->Id == 5246) //Intimidating Shout - TagUnitMap.remove(m_targets.getUnitTarget()); + Unit *target = m_targets.getUnitTarget(); + if(!target) + { + sLog.outError("SPELL: no chain unit target for spell ID %u", m_spellInfo->Id); + return; + } + + //Chain: 2, 6, 22, 25, 45, 77 + uint32 maxTargets = m_spellInfo->EffectChainTarget[i]; + if(modOwner) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, maxTargets, this); + + if(maxTargets > 1) + { + //otherwise, this multiplier is used for something else + m_damageMultipliers[i] = 1.0f; + m_applyMultiplierMask |= 1 << i; + + float radius; + std::list<Unit*> unitList; - Trinity::RandomResizeList(TagUnitMap, unMaxTargets); + switch(cur) + { + case TARGET_UNIT_NEARBY_ENEMY: + case TARGET_UNIT_TARGET_ENEMY: + case TARGET_UNIT_NEARBY_ENTRY: // fix me + radius = GetSpellRadius(m_spellInfo, i, false); + if(modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius, this); + SearchChainTarget(unitList, radius, maxTargets, SPELL_TARGETS_ENEMY); + break; + case TARGET_UNIT_CHAINHEAL: + case TARGET_UNIT_NEARBY_ALLY: // fix me + case TARGET_UNIT_NEARBY_ALLY_UNK: + case TARGET_UNIT_NEARBY_RAID: + radius = GetSpellRadius(m_spellInfo, i, true); + if(modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius, this); + SearchChainTarget(unitList, radius, maxTargets, SPELL_TARGETS_CHAINHEAL); + break; + } + + for(std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr) + AddUnitTarget(*itr, i); + } + else + AddUnitTarget(target, i); } -} + else if(pushType) + { + // Dummy, just for client + if(spellmgr.EffectTargetType[m_spellInfo->Effect[i]] == SPELL_REQUIRE_DEST) + return; -class PrioritizeManaPlayerWraper -{ - friend struct PrioritizeMana; + float radius; + SpellTargets targetType; + switch(cur) + { + case TARGET_UNIT_AREA_ENEMY_SRC: + case TARGET_UNIT_AREA_ENEMY_DST: + case TARGET_UNIT_CONE_ENEMY: + case TARGET_UNIT_CONE_ENEMY_UNKNOWN: + radius = GetSpellRadius(m_spellInfo, i, false); + targetType = SPELL_TARGETS_ENEMY; + break; + case TARGET_UNIT_AREA_ALLY_SRC: + case TARGET_UNIT_AREA_ALLY_DST: + case TARGET_UNIT_CONE_ALLY: + radius = GetSpellRadius(m_spellInfo, i, true); + targetType = SPELL_TARGETS_ALLY; + break; + case TARGET_UNIT_AREA_ENTRY_SRC: + case TARGET_UNIT_AREA_ENTRY_DST: + case TARGET_UNIT_CONE_ENTRY: // fix me + radius = GetSpellRadius(m_spellInfo, i, IsPositiveSpell(m_spellInfo->Id)); + targetType = SPELL_TARGETS_ENTRY; + break; + default: + radius = GetSpellRadius(m_spellInfo, i, true); + targetType = SPELL_TARGETS_NONE; + break; + } + + if(modOwner) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius, this); - public: - explicit PrioritizeManaPlayerWraper(Player* player) : player(player) + std::list<Unit*> unitList; + if(targetType == SPELL_TARGETS_ENTRY) { - uint32 maxmana = player->GetMaxPower(POWER_MANA); - percentMana = maxmana ? player->GetPower(POWER_MANA) * 100 / maxmana : 101; + SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id); + SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); + if(lower == upper) + { + sLog.outErrorDb("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry()); + + if(IsPositiveEffect(m_spellInfo->Id, i)) + SearchAreaTarget(unitList, radius, PUSH_DST_CENTER, SPELL_TARGETS_ALLY); + else + SearchAreaTarget(unitList, radius, PUSH_DST_CENTER, SPELL_TARGETS_ENEMY); + } + // let it be done in one check? + else + { + for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST) + { + if(i_spellST->second.type == SPELL_TARGET_TYPE_CREATURE) + SearchAreaTarget(unitList, radius, PUSH_DST_CENTER, SPELL_TARGETS_ENTRY, i_spellST->second.targetEntry); + } + } } - Player* getPlayer() const { return player; } - private: - Player* player; - uint32 percentMana; -}; + else if(targetType) + SearchAreaTarget(unitList, radius, pushType, targetType); + else + { + switch(cur) + { + case TARGET_UNIT_AREA_PARTY_SRC: + case TARGET_UNIT_AREA_PARTY_DST: + m_caster->GetPartyMember(unitList, radius); //fix me + break; + case TARGET_OBJECT_AREA_SRC: // fix me + case TARGET_OBJECT_AREA_DST: + break; + case TARGET_UNIT_PARTY_TARGET: + m_targets.getUnitTarget()->GetPartyMember(unitList, radius); + break; + case TARGET_UNIT_PARTY_CASTER: + m_caster->GetPartyMember(unitList, radius); + break; + case TARGET_UNIT_RAID_CASTER: + m_caster->GetRaidMember(unitList, radius); + break; + case TARGET_UNIT_CLASS_TARGET: + { + Player* targetPlayer = m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER + ? (Player*)m_targets.getUnitTarget() : NULL; -struct PrioritizeMana -{ - int operator()( PrioritizeManaPlayerWraper const& x, PrioritizeManaPlayerWraper const& y ) const - { - return x.percentMana < y.percentMana; - } -}; + Group* pGroup = targetPlayer ? targetPlayer->GetGroup() : NULL; + if(pGroup) + { + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* Target = itr->getSource(); + + // IsHostileTo check duel and controlled by enemy + if( Target && targetPlayer->IsWithinDistInMap(Target, radius) && + targetPlayer->getClass() == Target->getClass() && + !m_caster->IsHostileTo(Target) ) + { + AddUnitTarget(Target, i); + } + } + } + else if(m_targets.getUnitTarget()) + AddUnitTarget(m_targets.getUnitTarget(), i); + break; + } + } + } + + if(!unitList.empty()) + { + if(m_spellValue->MaxAffectedTargets) + { + if(m_spellInfo->Id == 5246) //Intimidating Shout + unitList.remove(m_targets.getUnitTarget()); + Trinity::RandomResizeList(unitList, m_spellValue->MaxAffectedTargets); + } + + for(std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr) + AddUnitTarget(*itr, i); + } + } // Chain or Area +} void Spell::prepare(SpellCastTargets const* targets, AuraEffect* triggeredByAura) { @@ -2485,8 +2515,8 @@ void Spell::_handle_immediate_phase() { if(spellmgr.EffectTargetType[m_spellInfo->Effect[j]] == SPELL_REQUIRE_DEST) { - if(!m_targets.HasDest()) - m_targets.setDestination(m_caster, false); + if(!m_targets.HasDst()) + m_targets.setDestination(m_caster); HandleEffects(m_originalCaster, NULL, NULL, j); } else if(spellmgr.EffectTargetType[m_spellInfo->Effect[j]] == SPELL_REQUIRE_NONE) @@ -3701,7 +3731,7 @@ SpellCastResult Spell::CheckCast(bool strict) // If 0 spell effect empty - client not send target data (need use selection) // TODO: check it on next client version if (m_targets.m_targetMask == TARGET_FLAG_SELF && - m_spellInfo->EffectImplicitTargetA[1] == TARGET_CHAIN_DAMAGE) + m_spellInfo->EffectImplicitTargetA[1] == TARGET_UNIT_TARGET_ENEMY) { if (target = m_caster->GetUnit(*m_caster, ((Player *)m_caster)->GetSelection())) m_targets.setUnitTarget(target); @@ -3713,7 +3743,7 @@ SpellCastResult Spell::CheckCast(bool strict) // check pet presents for(int j=0;j<3;j++) { - if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_PET) + if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_UNIT_PET) { target = m_caster->GetGuardianPet(); if(!target) @@ -3831,15 +3861,15 @@ SpellCastResult Spell::CheckCast(bool strict) { for(uint8 j = 0; j < 3; j++) { - if( m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT || - m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT && m_spellInfo->EffectImplicitTargetA[j] != TARGET_SELF || - m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || - m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES ) + if( m_spellInfo->EffectImplicitTargetA[j] == TARGET_UNIT_NEARBY_ENTRY || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_UNIT_NEARBY_ENTRY && m_spellInfo->EffectImplicitTargetA[j] != TARGET_UNIT_CASTER || + m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_DST_NEARBY_ENTRY ) { SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id); SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); if(lower==upper) - sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = TARGET_SCRIPT or TARGET_SCRIPT_COORDINATES, but does not have record in `spell_script_target`",m_spellInfo->Id); + sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = TARGET_UNIT_NEARBY_ENTRY or TARGET_DST_NEARBY_ENTRY, but does not have record in `spell_script_target`",m_spellInfo->Id); SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex); float range = GetSpellMaxRange(srange); @@ -3920,31 +3950,31 @@ SpellCastResult Spell::CheckCast(bool strict) if(creatureScriptTarget) { - // store coordinates for TARGET_SCRIPT_COORDINATES - if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || - m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES ) + // store coordinates for TARGET_DST_NEARBY_ENTRY + if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_DST_NEARBY_ENTRY ) { m_targets.setDestination(creatureScriptTarget->GetPositionX(),creatureScriptTarget->GetPositionY(),creatureScriptTarget->GetPositionZ()); - if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) + if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) AddUnitTarget(creatureScriptTarget, j); } - // store explicit target for TARGET_SCRIPT + // store explicit target for TARGET_UNIT_NEARBY_ENTRY else AddUnitTarget(creatureScriptTarget, j); } else if(goScriptTarget) { - // store coordinates for TARGET_SCRIPT_COORDINATES - if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || - m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES ) + // store coordinates for TARGET_DST_NEARBY_ENTRY + if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_DST_NEARBY_ENTRY ) { m_targets.setDestination(goScriptTarget->GetPositionX(),goScriptTarget->GetPositionY(),goScriptTarget->GetPositionZ()); - if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) + if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) AddGOTarget(goScriptTarget, j); } - // store explicit target for TARGET_SCRIPT + // store explicit target for TARGET_UNIT_NEARBY_ENTRY else AddGOTarget(goScriptTarget, j); } @@ -4008,7 +4038,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (m_caster->GetTypeId() != TYPEID_PLAYER) return SPELL_FAILED_BAD_TARGETS; - if(m_spellInfo->EffectImplicitTargetA[i] != TARGET_PET) + if(m_spellInfo->EffectImplicitTargetA[i] != TARGET_UNIT_PET) break; Pet* pet = ((Player*)m_caster)->GetPet(); @@ -4430,7 +4460,7 @@ SpellCastResult Spell::CheckPetCast(Unit* target) bool need = false; for(uint32 i = 0;i<3;i++) { - if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_CHAIN_DAMAGE || m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_FRIEND || m_spellInfo->EffectImplicitTargetA[i] == TARGET_DUELVSPLAYER || m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_PARTY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_CURRENT_ENEMY_COORDINATES) + if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ENEMY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ALLY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ANY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_PARTY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_DST_TARGET_ENEMY) { need = true; if(!target) @@ -4797,8 +4827,8 @@ SpellCastResult Spell::CheckItems() SpellCastResult failReason = SPELL_CAST_OK; for (int i = 0; i < 3; i++) { - // skip check, pet not required like checks, and for TARGET_PET m_targets.getUnitTarget() is not the real target but the caster - if (m_spellInfo->EffectImplicitTargetA[i] == TARGET_PET) + // skip check, pet not required like checks, and for TARGET_UNIT_PET m_targets.getUnitTarget() is not the real target but the caster + if (m_spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_PET) continue; if (m_spellInfo->Effect[i] == SPELL_EFFECT_HEAL) @@ -5356,10 +5386,10 @@ CurrentSpellTypes Spell::GetCurrentContainer() return(CURRENT_GENERIC_SPELL); } -bool Spell::CheckTarget( Unit* target, uint32 eff ) +bool Spell::CheckTarget(Unit* target, uint32 eff) { // Check targets for creature type mask and remove not appropriate (skip explicit self target case, maybe need other explicit targets) - if(m_spellInfo->EffectImplicitTargetA[eff]!=TARGET_SELF) + if(m_spellInfo->EffectImplicitTargetA[eff]!=TARGET_UNIT_CASTER) { if (!CheckTargetCreatureType(target)) return false; @@ -5379,11 +5409,11 @@ bool Spell::CheckTarget( Unit* target, uint32 eff ) if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) return false; - // unselectable targets skipped in all cases except TARGET_SCRIPT targeting - // in case TARGET_SCRIPT target selected by server always and can't be cheated + // unselectable targets skipped in all cases except TARGET_UNIT_NEARBY_ENTRY targeting + // in case TARGET_UNIT_NEARBY_ENTRY target selected by server always and can't be cheated /*if( target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE) && - m_spellInfo->EffectImplicitTargetA[eff] != TARGET_SCRIPT && - m_spellInfo->EffectImplicitTargetB[eff] != TARGET_SCRIPT ) + m_spellInfo->EffectImplicitTargetA[eff] != TARGET_UNIT_NEARBY_ENTRY && + m_spellInfo->EffectImplicitTargetB[eff] != TARGET_UNIT_NEARBY_ENTRY ) return false;*/ } |