Esempio n. 1
0
/// Spell Target Handling for type 37: all Members of the targets party
void Spell::SpellTargetPartyMember(uint32 i, uint32 j)
{
	if(!m_caster->IsInWorld())
		return;

	TargetsList* tmpMap=&m_targetUnits[i];
	// 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;

	float rsqr = GetRadius( i );
	if( rsqr == 0 )
		rsqr = 40*40;//kinda like a bug. 0 range to target a party member ? Highly impossible
	else rsqr *= rsqr;	
	if(subgroup)
	{
		Target->GetGroup()->Lock();
		for(GroupMembersSet::iterator itr = subgroup->GetGroupMembersBegin(); itr != subgroup->GetGroupMembersEnd(); ++itr)
			//if you are picky you could also check if on same map. Let's face it you won't similar positions on different maps
			if((*itr)->m_loggedInPlayer && IsInrange(Target,(*itr)->m_loggedInPlayer, rsqr) )
				SafeAddTarget(tmpMap,(*itr)->m_loggedInPlayer->GetGUID());
		Target->GetGroup()->Unlock();
	}
	else
	{
		SafeAddTarget(tmpMap,Target->GetGUID());
	}
}
Esempio n. 2
0
/// Spell Target Handling for type 18: All Party Members around the Caster in given range NOT RAID
void Spell::SpellTargetAllPartyMembersRangeNR(uint32 i, uint32 j)
{
	TargetsList* tmpMap = &m_targetUnits[i];
	Player* p = p_caster;

	if( p == NULL )
	{
		if( static_cast< Creature* >( u_caster)->IsTotem() )
			p = static_cast< Player* >( static_cast< Creature* >( u_caster )->GetTotemOwner() );
		else if( u_caster->IsPet() && static_cast< Pet* >( u_caster )->GetPetOwner() ) 
			p = static_cast< Pet* >( u_caster )->GetPetOwner();
		else if( u_caster->GetUInt64Value( UNIT_FIELD_CREATEDBY ) )
		{
			Unit *t = u_caster->GetMapMgr()->GetUnit( u_caster->GetUInt64Value( UNIT_FIELD_CREATEDBY ) );
			if ( t && t->IsPlayer() )
				p = static_cast< Player* >( t );
		}
	}

	if( p == NULL )
		return;

	float r = GetRadius(i);

	r *= r;
	if( IsInrange( m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), p, r ) )
		SafeAddTarget( tmpMap, p->GetGUID() );	 

	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))
				SafeAddTarget(tmpMap,(*itr)->m_loggedInPlayer->GetGUID());
		}
		p->GetGroup()->Unlock();
	}
}
Esempio n. 3
0
/// Spell Target Handling for type 33: Party members of totem, inside given range
void Spell::SpellTargetNearbyPartyMembers(uint32 i, uint32 j)
{
	TargetsList* tmpMap=&m_targetUnits[i];
	// this implementation is wrong.... this one is for totems
	if( u_caster != NULL )
	{
		if( u_caster->GetTypeId()==TYPEID_UNIT)
		{
			if( static_cast< Creature* >( u_caster )->IsTotem() )
			{
				float r = GetRadius(i);
				r *= r;

				Player* p = static_cast< Player* >( static_cast< Creature* >( u_caster )->GetTotemOwner() );
				
				if( p == NULL)
					return;

				if(IsInrange(m_caster->GetPositionX(),m_caster->GetPositionY(),m_caster->GetPositionZ(),p,r))
					SafeAddTarget(tmpMap,p->GetGUID());

				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))
							SafeAddTarget(tmpMap,(*itr)->m_loggedInPlayer->GetGUID());
					}
					p->GetGroup()->Unlock();
				}
			}
		}
	}
}
Esempio n. 4
0
// 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);
}
Esempio n. 5
0
/// 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();
				}
			}
		}
	}
}
Esempio n. 6
0
/// 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);
}
Esempio n. 7
0
/// 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();
	}
}
Esempio n. 8
0
/// Spell Target Handling for type 57: Targeted Party Member
void Spell::SpellTargetTargetPartyMember(uint32 i, uint32 j)
{
	if(!m_caster->IsInWorld())
		return;

	if (!m_caster->IsPet() && !m_caster->IsPlayer())
		return;

	TargetsList* tmpMap=&m_targetUnits[i];
	Unit* Target = m_caster->GetMapMgr()->GetUnit(m_targets.m_unitTarget);
	Unit* Caster = static_cast<Unit*>(m_caster);

	if(!Target || !Caster)
		return;

	if (!Target->IsPet() && !Target->IsPlayer())
		return;

	if (Caster->IsPet() && static_cast<Pet*>(Caster)->GetPetOwner() != NULL)
		Caster = static_cast<Pet*>(Caster)->GetPetOwner();

	if(Target->IsPet() && static_cast<Pet*>(Target)->GetPetOwner() != NULL)
		Target = static_cast<Pet*>(Target)->GetPetOwner();

		

	if (Caster != Target)
	{
		Group *c_group = static_cast<Player*>(Caster)->GetGroup();

		if( !c_group )
			return; //caster or caster master are not in group, cannot cast spell on this target

		Group *t_group = static_cast<Player*>(Target)->GetGroup();

		if( !t_group )
			return; //target does not have a group

		if( t_group != c_group )
			return; //caster and target are not in same group

	}
	float r=GetMaxRange(dbcSpellRange.LookupEntry(GetProto()->rangeIndex));
	if(IsInrange(m_caster->GetPositionX(),m_caster->GetPositionY(),m_caster->GetPositionZ(),Target,r*r))
		SafeAddTarget(tmpMap,m_targets.m_unitTarget);
}
Esempio n. 9
0
void AI_DUMMY_TOWER::Update(uint32 p_time)
{
	//in case they managed somehow to move the tower then just put it back. Ex : deathgrip
	if( spawn_x != m_Unit->GetPositionX() )
	{
		m_Unit->SetPosition( spawn_x,spawn_y,spawn_z,m_Unit->GetOrientation(), false );
		WorldPacket data;
		m_Unit->BuildHeartBeatMsg( &data );
		m_Unit->SendMessageToSet( &data, false );
	}

	//let compiler optimize this. Function calls cannot be always optimized
	TickNow = GetTickCount();

	//constant Regen
	if( RegenStamp < TickNow )
	{
		m_Unit->SetUInt32Value( UNIT_FIELD_HEALTH, 500000 );
		m_Unit->SetUInt32Value( UNIT_FIELD_POWER1, 500000 );

		RegenStamp = TickNow + TOWER_REGEN_INTERVAL;

		WipeTargetList();	//we will never get to fight back :(

		//provide resource for those that are inrange
		for( set<Object*>::iterator itr = m_Unit->GetInRangeSetBegin(); itr != m_Unit->GetInRangeSetEnd(); ++itr)
		{
			if( (*itr) == NULL || (*itr)->IsInWorld() == false || (*itr)->IsPlayer() == false 
				|| (*itr)->GetUInt32Value( UNIT_FIELD_HEALTH ) == 0 || static_cast<Unit *>(*itr)->isAlive() == false
				)
				continue;

			if( IsInrange( m_Unit, (*itr), cur_range_sq ) == false )
				continue;

			PlayerResourceHolder *h = FetchHolder( static_cast<Player*>(*itr) );
			h->ResourceNow += ( TOWER_REGEN_INTERVAL / PLAYER_RESOURCE_SCALEDOWN );
		}
	}
}
Esempio n. 10
0
void AI_SUPPORT_TOWER::Update(uint32 p_time)
{
	//in case they managed somehow to move the tower then just put it back. Ex : deathgrip
	if( spawn_x != m_Unit->GetPositionX() )
	{
		m_Unit->SetPosition( spawn_x,spawn_y,spawn_z,m_Unit->GetOrientation(), false );
		WorldPacket data;
		m_Unit->BuildHeartBeatMsg( &data );
		m_Unit->SendMessageToSet( &data, false );
	}

	//if we are already casting something then ignore trying to cast again
//	if( m_Unit->isCasting() )
//		return;

	//let compiler optimize this. Function calls cannot be always optimized
	TickNow = GetTickCount();

	//constant Regen
	if( RegenStamp < TickNow )
	{
		//check for owner, if there is none then we may despawn
		Player *p = m_Unit->GetMapMgr()->GetPlayer( m_Unit->GetUInt64Value( UNIT_FIELD_CREATEDBY ) );
		//we may also despawn if we died
		if( ( ( p == NULL && m_Unit->GetUInt64Value( UNIT_FIELD_CREATEDBY ) ) || m_Unit->GetUInt32Value( UNIT_FIELD_HEALTH ) == 0 ) && m_Unit->IsCreature() )
		{
			static_cast<Creature *>( m_Unit )->Despawn( 0, 0 );
			RegenStamp = 0xFFFFFFFF;				//hopefully no more updates
			GlobalCoolDownFinished = 0xFFFFFFFF;	//hopefully no more updates
			return;
		}
		//award owner for spawning us
		if( p )
		{
			p->ModUnsigned32Value( PLAYER_FIELD_COINAGE, SpellCastsOnPlayers * sWorld.getRate(RATE_MONEY) * 10 );
			SpellCastsOnPlayers = 0;
		}

		//check if we got upgraded 
		EventLevelUp();

		RegenStamp = TickNow + TOWER_REGEN_INTERVAL;
		m_Unit->ModUnsigned32Value( UNIT_FIELD_HEALTH, in_combat_H_regen );
		if( m_Unit->GetUInt32Value( UNIT_FIELD_HEALTH ) > m_Unit->GetUInt32Value( UNIT_FIELD_MAXHEALTH ) )
			m_Unit->SetUInt32Value( UNIT_FIELD_HEALTH, m_Unit->GetUInt32Value( UNIT_FIELD_MAXHEALTH ) );
//		m_Unit->ModUnsigned32Value( UNIT_FIELD_POWER1, in_combat_P_regen );
//		if( m_Unit->GetUInt32Value( UNIT_FIELD_POWER1 ) > m_Unit->GetUInt32Value( UNIT_FIELD_MAXPOWER1 ) )
//			m_Unit->SetUInt32Value( UNIT_FIELD_POWER1, m_Unit->GetUInt32Value( UNIT_FIELD_MAXPOWER1 ) );
	}

	//we are still waiting to get a new chance to cast a spell
	if( GlobalCoolDownFinished >= TickNow )
		return;

	//see if we could find a new target
	if( NextTargetUpdateStamp < TickNow )
	{
		//do not spam search cause it might be slow
		NextTargetUpdateStamp = TickNow + TOWER_TARGET_AQUISITION_INTERVAL;

		bool self_heal = true;
		//our max visible list
		for( set<Object*>::iterator itr = m_Unit->GetInRangeSetBegin(); itr != m_Unit->GetInRangeSetEnd(); ++itr)
		{
			if( (*itr) == NULL || (*itr)->IsInWorld() == false || (*itr)->IsUnit() == false 
				|| (*itr)->GetUInt32Value( UNIT_FIELD_HEALTH ) == 0 || static_cast<Unit *>(*itr)->isAlive() == false
				|| (*itr)->GetEntry() == 123461	//dummy tower should not be targeted
				)
				continue;

			if( IsInrange( m_Unit, (*itr), cur_range_sq ) == false )
				continue;

//			if( isAttackable( m_Unit, (*itr) ) == true )
			if( MyIsAttackable( m_Unit, (*itr) ) == true )
			{
				if( TryNerfCast( static_cast<Unit*>(*itr) ) )
				{
					//count tower contribution to fight
					if( (*itr)->IsPlayer() )
						SpellCastsOnPlayers+=20;
					self_heal = false;
					break;
				}
			}
			else
			{
				if( TryBeneficCast( static_cast<Unit*>(*itr) ) )
				{
					//count tower contribution to fight
//					if( (*itr)->IsPlayer() )
//						SpellCastsOnPlayers+=20;
					self_heal = false;
					break;
				}
				if( static_cast<Unit*>(*itr)->GetPowerType() == POWER_TYPE_MANA )
				{
					(*itr)->ModUnsigned32Value( UNIT_FIELD_POWER1 , in_combat_P_regen );
					if( (*itr)->GetUInt32Value( UNIT_FIELD_POWER1 ) > (*itr)->GetUInt32Value( UNIT_FIELD_MAXPOWER1 ) )
						(*itr)->SetUInt32Value( UNIT_FIELD_POWER1, (*itr)->GetUInt32Value( UNIT_FIELD_MAXPOWER1 ) );
				}
			}
		}
		_UpdateTargets();	//requered to clean out hate list

		if( self_heal == true )
			TryBeneficCast( m_Unit );
	}
}
Esempio n. 11
0
/// 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;

	TargetsList* tmpMap=&m_targetUnits[i];
	//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() == static_cast< 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_FAdditionalTargets,(int32*)&jumps,m_spellInfo->SpellGroupType);
	}
	SafeAddTarget(tmpMap,firstTarget->GetGUID());
	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->isAlive() )
					continue;

				//we target stuff that has no full health. No idea if we must fill target list or not :(
				if( (*itr)->m_loggedInPlayer->GetUInt32Value( UNIT_FIELD_HEALTH ) == (*itr)->m_loggedInPlayer->GetUInt32Value( UNIT_FIELD_MAXHEALTH ) )
					continue;

				if( sWorld.Collision && u_caster != NULL )
				{
					if (u_caster->GetMapId() == (*itr)->m_loggedInPlayer->GetMapId() && !CollideInterface.CheckLOS(u_caster->GetMapId(),u_caster->GetPositionNC(),(*itr)->m_loggedInPlayer->GetPositionNC()))
						continue;
				}

				if( IsInrange(u_caster,(*itr)->m_loggedInPlayer, range) )
				{
					SafeAddTarget(tmpMap,(*itr)->m_loggedInPlayer->GetGUID());
					if(!--jumps)
					{
						p_caster->GetGroup()->Unlock();
						return;
					}
				}
			}
			p_caster->GetGroup()->Unlock();
		}
	}//find nearby friendly target
	else
	{
		std::set<Object*>::iterator itr;
		firstTarget->AquireInrangeLock(); //make sure to release lock before exit function !
		for( itr = firstTarget->GetInRangeSetBegin(); itr != firstTarget->GetInRangeSetEnd(); itr++ )
		{
			if( !(*itr)->IsUnit() || !((Unit*)(*itr))->isAlive())
				continue;

			//we target stuff that has no full health. No idea if we must fill target list or not :(
			if( (*itr)->GetUInt32Value( UNIT_FIELD_HEALTH ) == (*itr)->GetUInt32Value( UNIT_FIELD_MAXHEALTH ) )
				continue;

			if (sWorld.Collision) {
				if (u_caster->GetMapId() == (*itr)->GetMapId() && !CollideInterface.CheckLOS(u_caster->GetMapId(),u_caster->GetPositionNC(),(*itr)->GetPositionNC()))
					continue;
			}

			if(IsInrange(firstTarget,*itr, range))
			{
				if(!isAttackable(u_caster,(Unit*)(*itr)))
				{
					SafeAddTarget(tmpMap,(*itr)->GetGUID());
					if(!--jumps)
					{
						firstTarget->ReleaseInrangeLock();
						return;
					}
				}
			}
		}
		firstTarget->ReleaseInrangeLock();
	}
}
Esempio n. 12
0
/// Spell Target Handling for type 31: related to scripted effects
void Spell::SpellTargetScriptedEffects( uint32 i, uint32 j )
{
	// Circle of healing or Wild Growth
	// - target top 5 hp deficient raid members around target.
	if( GetProto()->NameHash == SPELL_HASH_CIRCLE_OF_HEALING || GetProto()->NameHash == SPELL_HASH_WILD_GROWTH )
	{
		if( p_caster == NULL || !p_caster->IsInWorld() )
			return;

		TargetsList* tmpMap = &m_targetUnits[i];
		Unit * pTarget = p_caster->GetMapMgr()->GetUnit( m_targets.m_unitTarget );

		if( !pTarget )
			return;
		
		if( p_caster == pTarget ||
			IsInrange( p_caster->GetPositionX(), p_caster->GetPositionY(), p_caster->GetPositionZ(), pTarget, GetMaxRange( dbcSpellRange.LookupEntry( GetProto()->rangeIndex ) ) ) )
			SafeAddTarget( tmpMap, pTarget->GetGUID() );	 
		else
		{
			cancastresult = SPELL_FAILED_OUT_OF_RANGE;
			return; // No point targeting others if the target is not in casting range.
		}

		Group * group = p_caster->GetGroup(); 
		if( group == NULL )
			return;

		std::vector<Player*> raidList;
		std::vector<Player*>::iterator itr;

		uint32 count = group->GetSubGroupCount();

		group->Lock();
		for( uint32 k = 0; k < count; k++ )
		{
			SubGroup * subgroup = group->GetSubGroup( k );
			if( subgroup )
			{
				for( GroupMembersSet::iterator itr = subgroup->GetGroupMembersBegin(); itr != subgroup->GetGroupMembersEnd(); ++itr )
				{
					if( (*itr)->m_loggedInPlayer && m_caster != (*itr)->m_loggedInPlayer && 
						IsInrange( pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), (*itr)->m_loggedInPlayer, GetRadius(i) ) )
						raidList.push_back( (*itr)->m_loggedInPlayer );
				}
			}
		}
		group->Unlock();

		std::sort( raidList.begin(), raidList.end(), hpLessThan );

		uint32 maxTargets = 4;
		if( GetProto()->NameHash == SPELL_HASH_CIRCLE_OF_HEALING && p_caster->HasSpell( 55675 ) ) // Glyph of circle of healing
			maxTargets++;

		for( itr = raidList.begin(); itr != raidList.end() && maxTargets > 0; ++itr, maxTargets-- )
		{
			SafeAddTarget( tmpMap, (*itr)->GetGUID() );
		}
	}
	else
		FillAllTargetsInArea( i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, GetRadius(i) );
}
Esempio n. 13
0
/// Spell Target Handling for type 6 and 77: Single Target Enemy (grep thinks 77 fits in 6)
void Spell::SpellTargetSingleTargetEnemy(uint32 i, uint32 j)
{
	if(!m_caster->IsInWorld())
		return;
	Unit * pTarget = m_caster->GetMapMgr()->GetUnit(m_targets.m_unitTarget);
	if(!pTarget)
		return;

	if(p_caster && p_caster == pTarget) // spell bug: target is supposed to be a single enemy, not self
	{
		if(GetProto())
			sLog.outDebug("Spell %lu has target single enemy, but is targeting the caster.", GetProto()->Id);
	}

	TargetsList* tmpMap=&m_targetUnits[i];
	if(m_spellInfo->TargetCreatureType && pTarget->GetTypeId()==TYPEID_UNIT)
	{		
		Creature* cr = static_cast< Creature* >( pTarget );
		
		if( cr == NULL )
			return;

		if( cr->GetCreatureInfo() )
			if(!(1<<(cr->GetCreatureInfo()->Type-1) & m_spellInfo->TargetCreatureType))
				return;
	}

	if(p_caster && pTarget != p_caster)
	{
		// this is mostly used for things like duels
		if(pTarget->IsPlayer() && !isAttackable(p_caster, pTarget, false))
		{
			cancastresult = SPELL_FAILED_BAD_TARGETS;
			return;
		}

		/* HACK FIX */
		/* Please replace if found correct way */
		/* SPELL_AURA_SPELL_MAGNET */
		int x;
		for( x = 0; x < 3; ++x )
			if( m_spellInfo->EffectApplyAuraName[x] == SPELL_AURA_MOD_POSSESS ||
				m_spellInfo->is_melee_spell )
				break;		

		if( pTarget && x == 3 && pTarget->m_magnetcaster != 0)
		{	
			Unit *MagnetTarget = pTarget->GetMapMgr()->GetUnit(pTarget->m_magnetcaster);
			if ( MagnetTarget && m_spellInfo->School )
			{
				m_magnetTarget = pTarget->m_magnetcaster;	
				pTarget = MagnetTarget; // Redirected
			}
		}
	}

	uint8 did_hit_result = DidHit(i,pTarget);
	if(did_hit_result != SPELL_DID_HIT_SUCCESS)
		SafeAddModeratedTarget(pTarget->GetGUID(), did_hit_result);
	else
		SafeAddTarget(tmpMap, pTarget->GetGUID());

	if( m_spellInfo->EffectChainTarget[i] )
	{
		//number of additional targets
		uint32 jumps = m_spellInfo->EffectChainTarget[i] - 1;

		// extra targets by auras
		if( u_caster )
			SM_FIValue( u_caster->SM_FAdditionalTargets,(int32*)&jumps, m_spellInfo->SpellGroupType );

		float range = GetMaxRange( dbcSpellRange.LookupEntry( m_spellInfo->rangeIndex ) );//this is probably wrong
		range *= range;
		std::set<Object*>::iterator itr,itr2;
		m_caster->AquireInrangeLock(); //make sure to release lock before exit function !
		for( itr2 = m_caster->GetInRangeSetBegin(); itr2 != m_caster->GetInRangeSetEnd(); )
		{
			itr = itr2;
			itr2++;
			if((*itr)->GetGUID()==m_targets.m_unitTarget)
				continue;
			if( !((*itr)->IsUnit()) || !((Unit*)(*itr))->isAlive() || 
				((*itr)->IsCreature() && ((Creature*)(*itr))->IsTotem()))
				continue;

			if( sWorld.Collision && u_caster != NULL )
			{
				if (u_caster->GetMapId() == (*itr)->GetMapId() && !CollideInterface.CheckLOS(u_caster->GetMapId(),u_caster->GetPositionNC(),(*itr)->GetPositionNC()))
					continue;
			}

			if(IsInrange(m_caster->GetPositionX(),m_caster->GetPositionY(),m_caster->GetPositionZ(),(*itr),range))
			{
				if(isAttackable(u_caster,(Unit*)(*itr)))
				{
					did_hit_result = DidHit(i,((Unit*)*itr));
					if(did_hit_result==SPELL_DID_HIT_SUCCESS)
						SafeAddTarget(tmpMap, (*itr)->GetGUID());
					else
						SafeAddModeratedTarget((*itr)->GetGUID(), did_hit_result);

					if(!--jumps)
					{
						m_caster->ReleaseInrangeLock();
						return;
					}
				}
			}
		}
		m_caster->ReleaseInrangeLock();
	}
}
Esempio n. 14
0
/// 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;
				}
			}
		}
	}
}
Esempio n. 15
0
// Spell Target Handling for type 6 and 77: Single Target Enemy (grep thinks 77 fits in 6)
void Spell::SpellTargetSingleTargetEnemy(uint32 i, uint32 j)
{
	if(!m_caster->IsInWorld())
		return;

	Unit* pTarget = m_caster->GetMapMgr()->GetUnit(m_targets.m_unitTarget);
	if(!pTarget)
		return;

	if(m_spellInfo->TargetCreatureType && pTarget->GetTypeId()==TYPEID_UNIT)
	{
		Creature* cr = TO_CREATURE( pTarget );

		if( cr == NULL )
			return;

		if( cr->GetCreatureInfo() )
			if(!(1<<(cr->GetCreatureInfo()->Type-1) & m_spellInfo->TargetCreatureType))
				return;
	}

	if(p_caster && pTarget != p_caster)
	{
		// this is mostly used for things like duels
		if(pTarget->IsPlayer() && !isAttackable(p_caster, pTarget, false))
		{
			cancastresult = SPELL_FAILED_BAD_TARGETS;
			return;
		}
	}

	// magnet!!!!!
	if( pTarget->IsPlayer() && TO_PLAYER(pTarget)->m_magnetAura != NULL && m_magnetTarget == NULL )
	{
		if(!m_spellInfo->is_melee_spell && GetType() == SPELL_DMG_TYPE_MAGIC )
		{
			// redirect it to the magnet
			m_magnetTarget = TO_PLAYER(pTarget)->m_magnetAura->GetUnitCaster();

			// clear the magnet aura
			TO_PLAYER(pTarget)->m_magnetAura->Remove();
		}
	}

	if( m_magnetTarget != NULL )
	{
		// if the target exists, shoot it at him.
		if( m_magnetTarget != NULL && m_magnetTarget->IsInWorld() && !m_magnetTarget->isDead() )
			pTarget = m_magnetTarget;
	}

	_AddTarget(pTarget, i);

	if(m_spellInfo->EffectChainTarget[i])
	{
		uint32 jumps=m_spellInfo->EffectChainTarget[i]-1;
		float range=GetMaxRange(dbcSpellRange.LookupEntry(m_spellInfo->rangeIndex));//this is probably wrong
		range*=range;
		unordered_set<Object*>::iterator itr;
		for( itr = m_caster->GetInRangeSetBegin(); itr != m_caster->GetInRangeSetEnd(); ++itr )
		{
			if((*itr)->GetGUID()==m_targets.m_unitTarget)
				continue;
			if( !((*itr)->IsUnit()) || !TO_UNIT(*itr)->isAlive())
				continue;

			if(IsInrange(m_caster->GetPositionX(),m_caster->GetPositionY(),m_caster->GetPositionZ(),(*itr),range))
			{
				if(isAttackable(u_caster,TO_UNIT(*itr)))
				{
					_AddTarget(TO_UNIT(*itr), i);
					if(!--jumps)
						return;
				}
			}
		}
	}
}
Esempio n. 16
0
void Spell::AddChainTargets(uint32 i, uint32 TargetType, float r, uint32 maxtargets)
{
	if(!m_caster->IsInWorld())
		return;

	Object* targ = m_caster->GetMapMgr()->_GetObject(m_targets.m_unitTarget);

	if(targ == NULL)
		return;

	TargetsList* list = &m_targetUnits[i];

	//if selected target is party member, then jumps on party
	Unit* firstTarget = NULL;

	if(targ->IsUnit())
		firstTarget = TO_UNIT(targ);
	else
		firstTarget = u_caster;

	bool RaidOnly = false;
	float range = GetMaxRange(dbcSpellRange.LookupEntry(m_spellInfo->rangeIndex));//this is probably wrong,
	//this is cast distance, not searching distance
	range *= range;

	//is this party only?
	Player* casterFrom = TO< Player* >(u_caster->GetPlayerOwner());
	Player* pfirstTargetFrom = TO< Player* >(firstTarget->GetPlayerOwner());

	if(casterFrom != NULL && pfirstTargetFrom != NULL && casterFrom->GetGroup() == pfirstTargetFrom->GetGroup())
		RaidOnly = true;

	uint32 jumps = m_spellInfo->EffectChainTarget[i];

	//range
	range /= jumps; //hacky, needs better implementation!

	if(m_spellInfo->SpellGroupType && u_caster != NULL)
		SM_FIValue(u_caster->SM_FAdditionalTargets, (int32*)&jumps, m_spellInfo->SpellGroupType);

	AddTarget(i, TargetType, firstTarget);

	if(jumps <= 1 || list->size() == 0) //1 because we've added the first target, 0 size if spell is resisted
		return;

	ObjectSet::iterator itr;
	for(itr = firstTarget->GetInRangeSetBegin(); itr != firstTarget->GetInRangeSetEnd(); itr++)
	{
		if(!(*itr)->IsUnit() || !TO_UNIT((*itr))->isAlive())
			continue;

		if(RaidOnly && !pfirstTargetFrom->InRaid(TO_UNIT(*itr)))
			continue;

		//healing spell, full health target = NONO
		if(IsHealingSpell(m_spellInfo) && TO_UNIT(*itr)->GetHealthPct() == 100)
			continue;

		size_t oldsize;

		if(IsInrange(firstTarget->GetPositionX(), firstTarget->GetPositionY(), firstTarget->GetPositionZ(), (*itr), range))
		{
			oldsize = list->size();
			AddTarget(i, TargetType, (*itr));
			if(list->size() == oldsize || list->size() >= jumps) //either out of jumps or a resist
				return;
		}
	}
}