/// Spell Target Handling for type 32 / 73: related to summoned pet or creature void Spell::SpellTargetSummon(uint32 i, uint32 j) {// Minion Target if(m_caster->GetUInt64Value(UNIT_FIELD_SUMMON) == 0) _AddTargetForced(m_caster->GetGUID(), i); else _AddTargetForced(m_caster->GetUInt64Value(UNIT_FIELD_SUMMON), i); }
// Spell Target Handling for type 37: all Members of the targets party void Spell::SpellTargetPartyMember(uint32 i, uint32 j) { if(!m_caster->IsInWorld()) return; // if no group target self Player* Target = m_caster->GetMapMgr()->GetPlayer((uint32)m_targets.m_unitTarget); if(!Target) return; SubGroup * subgroup = Target->GetGroup() ? Target->GetGroup()->GetSubGroup(Target->GetSubGroup()) : 0; if(subgroup) { Target->GetGroup()->Lock(); for(GroupMembersSet::iterator itr = subgroup->GetGroupMembersBegin(); itr != subgroup->GetGroupMembersEnd(); itr++) { if((*itr)->m_loggedInPlayer) _AddTargetForced( (*itr)->m_loggedInPlayer->GetGUID(), i ); } Target->GetGroup()->Unlock(); } else _AddTargetForced(Target->GetGUID(), i); }
// Spell Target Handling for type 61: targets with the same group/raid and the same class void Spell::SpellTargetSameGroupSameClass(uint32 i, uint32 j) { if(!m_caster->IsInWorld()) return; if( m_caster->IsPlayer() ) if( !TO_PLAYER(m_caster)->GetGroup() ) _AddTargetForced(m_caster->GetGUID(), i); Player* Target = m_caster->GetMapMgr()->GetPlayer((uint32)m_targets.m_unitTarget); if(!Target) return; if( m_caster->IsPlayer() && Target->IsPlayer() && Target->GetGroup() && (Target == m_caster || Target->GetGroup()->HasMember(TO_PLAYER(m_caster))) ) { Target->GetGroup()->Lock(); for( uint32 x = 0; x < Target->GetGroup()->GetSubGroupCount(); ++x ) { for(GroupMembersSet::iterator itr = Target->GetGroup()->GetSubGroup( x )->GetGroupMembersBegin(); itr != Target->GetGroup()->GetSubGroup( x )->GetGroupMembersEnd(); itr++) { if(!(*itr)->m_loggedInPlayer || Target->getClass() != (*itr)->m_loggedInPlayer->getClass()) continue; _AddTargetForced((*itr)->m_loggedInPlayer->GetGUID(), i); } } Target->GetGroup()->Unlock(); } }
/// Spell Target Handling for type 26: unit target/Item Target /// game object and item related... research pickpocket stuff void Spell::SpellTargetGameobject_itemTarget(uint32 i, uint32 j) { if( m_targets.m_unitTarget ) _AddTargetForced(m_targets.m_unitTarget, i); if( m_targets.m_itemTarget ) _AddTargetForced(m_targets.m_itemTarget, i); }
/// Spell Target Handling for type 0: Default targeting void Spell::SpellTargetDefault(uint32 i, uint32 j) { if(j==0 || (m_caster->IsPet() && j==1)) { if(m_targets.m_unitTarget) _AddTargetForced(m_targets.m_unitTarget, i); else if(m_targets.m_itemTarget) _AddTargetForced(m_targets.m_itemTarget, i); else if( m_spellInfo->Effect[i] == SPELL_EFFECT_ADD_FARSIGHT || m_spellInfo->Effect[i] == SPELL_EFFECT_SUMMON_DEMON || m_spellInfo->Effect[i] == SPELL_EFFECT_SUMMON_WILD ) _AddTargetForced(m_caster->GetGUID(), i); } }
/// Spell Target Handling for type 31: related to scripted effects void Spell::SpellTargetScriptedEffects(uint32 i, uint32 j) { if( m_spellInfo->NameHash == SPELL_HASH_WILD_GROWTH || m_spellInfo->NameHash == SPELL_HASH_CIRCLE_OF_HEALING ) { if( p_caster == NULL || !p_caster->IsInWorld() ) return; if( p_caster->GetGroup() ) { uint32 TargetCount = 0; p_caster->GetGroup()->Lock(); for(uint32 x = 0; x < p_caster->GetGroup()->GetSubGroupCount(); ++x) { if( TargetCount == 5 ) break; for(GroupMembersSet::iterator itr = p_caster->GetGroup()->GetSubGroup( x )->GetGroupMembersBegin(); itr != p_caster->GetGroup()->GetSubGroup( x )->GetGroupMembersEnd(); itr++) { if((*itr)->m_loggedInPlayer && TargetCount != 5) { Player* p_target = (*itr)->m_loggedInPlayer; if( p_caster->GetDistance2dSq( p_target ) <= 225 ) // both spells have 15yd range, change in future if needed { _AddTargetForced( (*itr)->m_loggedInPlayer->GetGUID(), i ); TargetCount += 1; } } } } p_caster->GetGroup()->Unlock(); } } else FillAllTargetsInArea(i,m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ,GetDBCCastTime(i)); }
/// Spell Target Handling for type 87 void Spell::SpellTargetAreaOfEffect87(uint32 i, uint32 j) { if( !m_caster || !m_caster->IsInWorld() ) return; _AddTargetForced(m_caster->GetGUID(), i); }
/// Spell Target Handling for type 4: Target is holder of the aura void Spell::SpellTargetFriendly(uint32 i, uint32 j) { // O f**k we are contagious... // this off course is not tested yet. if (p_caster) _AddTargetForced(p_caster->GetGUID(), i); }
/// Spell Target Handling for type 5: Target: Pet void Spell::SpellTargetPet(uint32 i, uint32 j) { if(p_caster) { if( p_caster->GetSummon() != NULL ) _AddTargetForced( p_caster->GetSummon()->GetGUID(), i ); } }
/// Spell Target Handling for type 94: Target: Vehicle void Spell::SpellTargetVehicle(uint32 i, uint32 j) { if(p_caster) { if( p_caster->m_CurrentVehicle != NULL ) _AddTargetForced( p_caster->m_CurrentVehicle->GetGUID(), i ); } }
// Spell Target Handling for type 35: Single Target Party Member (if not in party then the target can not be himself) // this one requeres more research void Spell::SpellTargetSingleTargetPartyMember(uint32 i, uint32 j) { if(!m_caster->IsInWorld()) return; Unit* Target = m_caster->GetMapMgr()->GetPlayer((uint32)m_targets.m_unitTarget); if(!Target) return; float r=GetMaxRange(dbcSpellRange.LookupEntry(m_spellInfo->rangeIndex)); if(IsInrange(m_caster->GetPositionX(),m_caster->GetPositionY(),m_caster->GetPositionZ(),Target,r*r)) _AddTargetForced(m_targets.m_unitTarget, i); }
/// Spell Target Handling for type 18: Land under caster void Spell::SpellTargetLandUnderCaster(uint32 i, uint32 j) /// I don't think this is the correct name for this one { if( m_spellInfo->Effect[i] != SPELL_EFFECT_SUMMON_DEMON && m_spellInfo->Effect[i] != SPELL_EFFECT_SUMMON_OBJECT_WILD && m_spellInfo->Effect[i] != SPELL_EFFECT_SUMMON_OBJECT_SLOT1 && m_spellInfo->Effect[i] != SPELL_EFFECT_SUMMON_OBJECT_SLOT2 && m_spellInfo->Effect[i] != SPELL_EFFECT_SUMMON_OBJECT_SLOT3 && m_spellInfo->Effect[i] != SPELL_EFFECT_SUMMON_OBJECT_SLOT4 ) FillAllTargetsInArea(i, m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), GetDBCCastTime(i)); else _AddTargetForced(m_caster->GetGUID(), i); }
/// Spell Target Handling for type 33: Party members of totem, inside given range void Spell::SpellTargetNearbyPartyMembers(uint32 i, uint32 j) { // this implementation is wrong.... this one is for totems if( u_caster != NULL ) { if( u_caster->GetTypeId()==TYPEID_UNIT) { if( TO_CREATURE( u_caster )->IsTotem() ) { float r = GetDBCCastTime(i); r *= r; Player* p = TO_PLAYER( TO_CREATURE(u_caster)->GetSummonOwner()); if( p == NULL) return; if(IsInrange(m_caster->GetPositionX(),m_caster->GetPositionY(),m_caster->GetPositionZ(),p,r)) _AddTargetForced(p->GetGUID(), i); SubGroup * pGroup = p->GetGroup() ? p->GetGroup()->GetSubGroup(p->GetSubGroup()) : 0; if(pGroup) { p->GetGroup()->Lock(); for(GroupMembersSet::iterator itr = pGroup->GetGroupMembersBegin(); itr != pGroup->GetGroupMembersEnd(); itr++) { if(!(*itr)->m_loggedInPlayer || p == (*itr)->m_loggedInPlayer) continue; if(IsInrange(m_caster->GetPositionX(),m_caster->GetPositionY(),m_caster->GetPositionZ(),(*itr)->m_loggedInPlayer,r)) _AddTargetForced((*itr)->m_loggedInPlayer->GetGUID(), i); } p->GetGroup()->Unlock(); } } } } }
/// Spell Target Handling for type 38: Dummy Target (Server-side script effect) void Spell::SpellTargetDummyTarget(uint32 i, uint32 j) { //TargetsList *tmpMap=&m_targetUnits[i]; if( m_spellInfo->Id == 51699 ) { if( p_caster ) { Aura* aur = p_caster->FindAura( 52916 ); if( aur && aur->GetUnitCaster() ) { _AddTargetForced(aur->GetUnitCaster()->GetGUID(), i); return; } } } else if( m_spellInfo->Id == 12938 ) { //FIXME:this ll be immortal targets FillAllTargetsInArea(i,m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ,GetDBCCastTime(i)); } _AddTargetForced(m_caster->GetGUID(), i); }
/// Spell Target Handling for type 21: Single Target Friend void Spell::SpellTargetSingleTargetFriend(uint32 i, uint32 j) { Unit* Target; if(m_targets.m_unitTarget == m_caster->GetGUID()) Target = u_caster; else Target = m_caster->GetMapMgr() ? m_caster->GetMapMgr()->GetUnit(m_targets.m_unitTarget) : NULL; if(!Target) return; float r= GetMaxRange(dbcSpellRange.LookupEntry(m_spellInfo->rangeIndex)); if(IsInrange (m_caster->GetPositionX(),m_caster->GetPositionY(),m_caster->GetPositionZ(),Target, r*r)) _AddTargetForced(Target->GetGUID(), i); }
/// Spell Target Handling for type 29: all object around the the caster / object (so it seems) void Spell::SpellTargetTypeTAOE(uint32 i, uint32 j) { Unit* Target = m_caster->GetMapMgr()->GetUnit(m_targets.m_unitTarget); if( Target == NULL ) return; // tranquility if( u_caster != NULL && m_spellInfo->NameHash == SPELL_HASH_TRANQUILITY ) _AddTargetForced(u_caster->GetGUID(), i); else { FillAllTargetsInArea( (LocationVector&)Target->GetPosition(), i ); } }
/// Spell Target Handling for type 18: All Party Members around the Caster in given range NOT RAID void Spell::SpellTargetAllPartyMembersRangeNR(uint32 i, uint32 j) { Player* p = p_caster; if( p == NULL ) { if( TO_CREATURE( u_caster)->IsTotem() ) p = TO_PLAYER( TO_CREATURE(u_caster)->GetSummonOwner()); else if( u_caster->IsPet() && TO_PET( u_caster )->GetPetOwner() ) p = TO_PET( u_caster )->GetPetOwner(); } if( p == NULL ) return; float r = GetDBCCastTime(i); r *= r; if( IsInrange( m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), p, r ) ) _AddTargetForced(p->GetGUID(), i); SubGroup* subgroup = p->GetGroup() ? p->GetGroup()->GetSubGroup( p->GetSubGroup() ) : 0; if( subgroup != NULL ) { p->GetGroup()->Lock(); for(GroupMembersSet::iterator itr = subgroup->GetGroupMembersBegin(); itr != subgroup->GetGroupMembersEnd(); itr++) { if(!(*itr)->m_loggedInPlayer || m_caster == (*itr)->m_loggedInPlayer) continue; if(IsInrange(m_caster->GetPositionX(),m_caster->GetPositionY(),m_caster->GetPositionZ(),(*itr)->m_loggedInPlayer,r)) _AddTargetForced( (*itr)->m_loggedInPlayer->GetGUID(), i ); } p->GetGroup()->Unlock(); } }
/// Spell Target Handling for type 45: Chain,!!only for healing!! for chain lightning =6 void Spell::SpellTargetChainTargeting(uint32 i, uint32 j) { if( !m_caster->IsInWorld() ) return; //if selected target is party member, then jumps on party Unit* firstTarget; bool PartyOnly = false; float range = GetMaxRange(dbcSpellRange.LookupEntry(m_spellInfo->rangeIndex));//this is probably wrong, //this is cast distance, not searching distance range *= range; firstTarget = m_caster->GetMapMgr()->GetPlayer((uint32)m_targets.m_unitTarget); if( firstTarget && p_caster != NULL ) { if( p_caster->InGroup() ) if( p_caster->GetSubGroup() == TO_PLAYER( firstTarget )->GetSubGroup() ) PartyOnly=true; } else { firstTarget = m_caster->GetMapMgr()->GetUnit(m_targets.m_unitTarget); if(!firstTarget) return; } uint32 jumps=m_spellInfo->EffectChainTarget[i]; if(m_spellInfo->SpellGroupType && u_caster) { SM_FIValue(u_caster->SM[SMT_ADDITIONAL_TARGET][0],(int32*)&jumps,m_spellInfo->SpellGroupType); } _AddTargetForced(firstTarget->GetGUID(), i); if(!jumps) return; jumps--; if(PartyOnly) { GroupMembersSet::iterator itr; SubGroup * pGroup = p_caster->GetGroup() ? p_caster->GetGroup()->GetSubGroup(p_caster->GetSubGroup()) : 0; if(pGroup) { p_caster->GetGroup()->Lock(); for(itr = pGroup->GetGroupMembersBegin(); itr != pGroup->GetGroupMembersEnd(); itr++) { if(!(*itr)->m_loggedInPlayer || (*itr)->m_loggedInPlayer == u_caster || (*itr)->m_loggedInPlayer->GetUInt32Value(UNIT_FIELD_HEALTH) == (*itr)->m_loggedInPlayer->GetUInt32Value(UNIT_FIELD_MAXHEALTH)) continue; if(IsInrange(u_caster->GetPositionX(),u_caster->GetPositionY(),u_caster->GetPositionZ(),(*itr)->m_loggedInPlayer, range)) { _AddTargetForced((*itr)->m_loggedInPlayer->GetGUID(), i); if(!--jumps) { p_caster->GetGroup()->Unlock(); return; } } } p_caster->GetGroup()->Unlock(); } }//find nearby friendly target else { unordered_set<Object*>::iterator itr; for( itr = firstTarget->GetInRangeSetBegin(); itr != firstTarget->GetInRangeSetEnd(); ++itr ) { if( !(*itr)->IsUnit() || !TO_UNIT(*itr)->isAlive()) continue; if(IsInrange(firstTarget->GetPositionX(),firstTarget->GetPositionY(),firstTarget->GetPositionZ(),*itr, range)) { if(!isAttackable(u_caster,TO_UNIT(*itr)) && (*itr)->GetUInt32Value(UNIT_FIELD_HEALTH) != (*itr)->GetUInt32Value(UNIT_FIELD_MAXHEALTH)) { _AddTargetForced((*itr)->GetGUID(), i); if(!--jumps) return; } } } } }
/// Spell Target Handling for type 41 / 42 / 43 / 44: Totems void Spell::SpellTargetTotem(uint32 i, uint32 j) { _AddTargetForced(m_caster->GetGUID(), i); }
/// Spell Target Handling for type 23: Gameobject Target void Spell::SpellTargetSingleGameobjectTarget(uint32 i, uint32 j) { _AddTargetForced(m_targets.m_unitTarget, i); }
/// Spell Target Handling for type 25: Single Target Friend // Used o.a. in Duel void Spell::SpellTargetSingleFriend(uint32 i, uint32 j) { _AddTargetForced(m_targets.m_unitTarget, i); }
void Spell::SpellTargetSimpleTargetAdd(uint32 i, uint32 j) { _AddTargetForced(m_caster->GetGUID(), i); }
/// Spell Target Handling for type 27: target is owner of pet void Spell::SpellTargetPetOwner(uint32 i, uint32 j) { if( u_caster->IsPet() && TO_PET(u_caster)->GetPetOwner() ) _AddTargetForced( TO_PET(u_caster)->GetPetOwner()->GetGUID(), i ); }
bool Spell::AddTarget(uint32 i, uint32 TargetType, Object* obj) { if(obj == NULL || !obj->IsInWorld()) return false; //GO target, not item if((TargetType & SPELL_TARGET_REQUIRE_GAMEOBJECT) && !(TargetType & SPELL_TARGET_REQUIRE_ITEM) && !obj->IsGameObject()) return false; //target go, not able to target go if(obj->IsGameObject() && !(TargetType & SPELL_TARGET_OBJECT_SCRIPTED) && !(TargetType & SPELL_TARGET_REQUIRE_GAMEOBJECT) && !m_triggeredSpell) return false; //target item, not able to target item if(obj->IsItem() && !(TargetType & SPELL_TARGET_REQUIRE_ITEM) && !m_triggeredSpell) return false; if(u_caster != NULL && u_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9) && ((obj->IsPlayer() || obj->IsPet()) || (p_caster != NULL || m_caster->IsPet()))) return false; if(TargetType & SPELL_TARGET_REQUIRE_FRIENDLY && !sFactionSystem.isFriendly(m_caster, obj)) return false; if(TargetType & SPELL_TARGET_REQUIRE_ATTACKABLE && !sFactionSystem.isAttackable(m_caster, obj)) return false; if(TargetType & SPELL_TARGET_OBJECT_TARCLASS) { Object* originaltarget = m_caster->GetMapMgr()->_GetObject(m_targets.m_unitTarget); if(originaltarget == NULL || (originaltarget->IsPlayer() && obj->IsPlayer() && TO_PLAYER(originaltarget)->getClass() != TO_PLAYER(obj)->getClass()) || (originaltarget->IsPlayer() && !obj->IsPlayer()) || (!originaltarget->IsPlayer() && obj->IsPlayer())) return false; } if(TargetType & SPELL_TARGET_OBJECT_CURPET && !obj->IsPet()) return false; if(TargetType & (SPELL_TARGET_AREA | SPELL_TARGET_AREA_SELF | SPELL_TARGET_AREA_CURTARGET | SPELL_TARGET_AREA_CONE | SPELL_TARGET_AREA_PARTY | SPELL_TARGET_AREA_RAID) && ((obj->IsUnit() && !TO_UNIT(obj)->isAlive()) || (obj->IsCreature() && obj->IsTotem()))) return false; if(TargetType & SPELL_TARGET_REQUIRE_ATTACKABLE && obj->IsUnit()) _AddTarget(TO_UNIT(obj), i); else _AddTargetForced(obj->GetGUID(), i); //final checks, require line of sight unless range/radius is 50000 yards SpellRange* r = dbcSpellRange.LookupEntry(m_spellInfo->rangeIndex); if(sWorld.Collision && r->maxRangeHostile < 50000 && GetRadius(i) < 50000 && !obj->IsItem()) { float x = m_caster->GetPositionX(), y = m_caster->GetPositionY(), z = m_caster->GetPositionZ() + 0.5f; //are we using a different location? if(TargetType & SPELL_TARGET_AREA) { x = m_targets.m_destX; y = m_targets.m_destY; z = m_targets.m_destZ; } else if(TargetType & SPELL_TARGET_AREA_CHAIN) { //TODO: Add support for this in arcemu /*Object* lasttarget = NULL; if (m_orderedObjects.size() > 0) { lasttarget = m_caster->GetMapMgr()->_GetObject(m_orderedObjects[m_orderedObjects.size() - 1]); if (lasttarget != NULL) { x = lasttarget->GetPositionX(); y = lasttarget->GetPositionY(); z = lasttarget->GetPositionZ(); } }*/ } if(!sVMapInterface.CheckLOS(m_caster->GetMapId(), m_caster->GetInstanceID(), m_caster->GetPhaseMask(), x, y, z + 2, obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ() + 2)) return false; } return true; }