Beispiel #1
0
void DynamicObject::AddInRangeObject( Object* pObj )
{
	if( pObj->IsUnit() )
	{
		bool attackable;
		if( p_caster != NULL)
			attackable = isAttackable( m_caster, pObj );
		else
			attackable = isAttackable( TO_DYNAMICOBJECT(this), pObj );
		
		if( attackable )
			m_inRangeOppFactions.insert( TO_UNIT( pObj ) );
	}
	Object::AddInRangeObject( pObj );
}
Beispiel #2
0
void DynamicObject::AddInRangeObject(Object* pObj)
{
	if(pObj->IsUnit())
	{
		bool attackable;
		if(p_caster)
			attackable = isAttackable(p_caster, pObj);
		else
			attackable = isAttackable(this, pObj);
		
		if(attackable)
			m_inRangeOppFactions.insert(((Unit*)pObj));
	}
	Object::AddInRangeObject(pObj);
}
Beispiel #3
0
/// Spell Target Handling for type 54: Targets in Front of the Caster
void Spell::SpellTargetInFrontOfCaster2(uint32 i, uint32 j)
{
	TargetsList* tmpMap=&m_targetUnits[i];
	std::set<Object*>::iterator itr,itr2;
	uint8 did_hit_result;
	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)->IsUnit()) || !((Unit*)(*itr))->isAlive())
			continue;
		//is Creature in range
		if(m_caster->isInRange((Unit*)(*itr),GetRadius(i)))
		{
			if(m_caster->isInFront((Unit*)(*itr)))
			{
				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);
				}	
			}
		}
	}
	m_caster->ReleaseInrangeLock();
}
Beispiel #4
0
/// Spell Target Handling for type 24: Targets in Front of the Caster
void Spell::SpellTargetInFrontOfCaster(uint32 i, uint32 j)
{
	TargetsList* tmpMap=&m_targetUnits[i];
	std::set<Object*>::iterator itr;
	uint8 did_hit_result;
	m_caster->AquireInrangeLock(); //make sure to release lock before exit function !
	for( itr = m_caster->GetInRangeSetBegin(); itr != m_caster->GetInRangeSetEnd(); itr++ )
	{
		if(!((*itr)->IsUnit()) || !((Unit*)(*itr))->isAlive())
			continue;
		//is Creature in range
		if(m_caster->isInRange((Unit*)(*itr),GetRadius(i)))
		{
			if (sWorld.Collision) {
				if (m_caster->GetMapId() == (*itr)->GetMapId() && !CollideInterface.CheckLOS(m_caster->GetMapId(),m_caster->GetPositionNC(),(*itr)->GetPositionNC()))
					continue;
			}

			if( m_spellInfo->cone_width ? m_caster->isInArc( (Unit*)(*itr) , m_spellInfo->cone_width ) : m_caster->isInFront((Unit*)(*itr)) ) // !!! is the target within our cone ?
			{
				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);
				}	
			}
		}
	}
	m_caster->ReleaseInrangeLock();
}
bool Pestilence(uint32 i, Spell* pSpell)
{
	if(i == 1) // Script Effect that has been identified to handle the spread of diseases.
	{
		if(!pSpell->u_caster || !pSpell->u_caster->GetTargetGUID() || !pSpell->u_caster->IsInWorld())
			return true;

		Unit* u_caster = pSpell->u_caster;
		Unit* Main = u_caster->GetMapMgr()->GetUnit(u_caster->GetTargetGUID());
		if(Main == NULL)
			return true;
		bool blood = Main->HasAura(BLOOD_PLAGUE);
		bool frost = Main->HasAura(FROST_FEVER);
		int inc = (u_caster->HasAura(59309) ? 10 : 5);
		for(Object::InRangeSet::iterator itr = u_caster->GetInRangeSetBegin(); itr != u_caster->GetInRangeSetEnd(); ++itr)
		{
			if(!(*itr)->IsUnit())
				continue;
			Unit* Target = TO< Unit* >((*itr));
			if(Main->GetGUID() == Target->GetGUID() && !u_caster->HasAura(63334))
				continue;
			if(isAttackable(Target, u_caster) && u_caster->CalcDistance((*itr)) <= (pSpell->GetRadius(i) + inc))
			{
				if(blood)
					u_caster->CastSpell(Target, BLOOD_PLAGUE, true);
				if(frost)
					u_caster->CastSpell(Target, FROST_FEVER, true);
			}
		}
		return true;
	}
	return true;
}
Beispiel #6
0
void DynamicObject::RemoveInRangeObject(Object* pObj)
{
    if(pObj->IsUnit())
    {
        bool attackable;
        if(p_caster)
            attackable = isAttackable(p_caster, pObj);
        else
            attackable = isAttackable(this, pObj);

        if(attackable)
            m_inRangeOppFactions.erase(((Unit*)pObj));

        targets.erase(((Unit*)pObj));
    }
    Object::RemoveInRangeObject(pObj);
}
Beispiel #7
0
bool Penance(uint32 i, Spell * pSpell)
{
	if( !pSpell->p_caster || !pSpell->p_caster->isAlive() || 
		!pSpell->GetUnitTarget() || !pSpell->GetUnitTarget()->isAlive() )
		return false;

	Unit *target = pSpell->GetUnitTarget();
	Player *player = pSpell->p_caster;

	// index 0 contains the spell for the first tick, index 1 is the peroidic cast spell.
	uint32 hostileSpell[] = {0, 0};
	uint32 friendlySpell[] = {0, 0};

	switch( pSpell->GetProto()->Id )
	{
	case 47540: //Rank 1
		hostileSpell[0] = 47666;
		hostileSpell[1] = 47758;

		friendlySpell[0] = 47750;
		friendlySpell[1] = 47757;
		break;
	case 53005:
		hostileSpell[0] = 52998;
		hostileSpell[1] = 53001;

		friendlySpell[0] = 52983;
		friendlySpell[1] = 52986;
		break;
	case 53006:
		hostileSpell[0] = 52999;
		hostileSpell[1] = 53002;

		friendlySpell[0] = 52984;
		friendlySpell[1] = 52987;
		break;
	case 53007:
		hostileSpell[0] = 53000;
		hostileSpell[1] = 53003;

		friendlySpell[0] = 52985;
		friendlySpell[1] = 52988;
		break;
	}

	if( isAttackable(player, target) ) // Do holy damage
	{
		// First tick is instant.
		player->CastSpell(target, hostileSpell[0], true);
		player->CastSpell(target, hostileSpell[1], false);
	}
	else // Heal
	{ 
		player->CastSpell(target, friendlySpell[0], true);
		player->CastSpell(target, friendlySpell[1], false);
	}
	return true;
}
Beispiel #8
0
bool HolyShock(uint32 i, Spell *pSpell)
{
	Unit *target = pSpell->GetUnitTarget();
	if(!pSpell->p_caster || !target) return true;

	uint32 newspell = 0;

	if(isAttackable(pSpell->p_caster,target)) // if its an enemy
	{
		switch(pSpell->GetProto()->Id)
		{
		case 20473:
			newspell = 25912;
			break;
		case 20929:
			newspell = 25911;
			break;
		case 20930:
			newspell = 25902;
			break;
		case 27174:
			newspell = 27176;
			break;
		case 33072:
			newspell = 33073;
			break;
		}
	}
	else // if its friendly
	{
		switch(pSpell->GetProto()->Id)
		{
		case 20473:
			newspell = 25914;
			break;
		case 20929:
			newspell = 25913;
			break;
		case 20930:
			newspell = 25903;
			break;
		case 27174:
			newspell = 27175;
			break;
		case 33072:
			newspell = 33074;
			break;
		}
	}

	SpellEntry *spInfo = dbcSpell.LookupEntry(newspell);
	if(!spInfo) return true;

	pSpell->p_caster->CastSpell(target, spInfo, true);
	return true;
}
Beispiel #9
0
/// Spell Target Handling for type 24: Targets in Front of the Caster
void Spell::SpellTargetInFrontOfCaster(uint32 i, uint32 j)
{
	unordered_set<Object*>::iterator itr,itr2;

	if( m_spellInfo->cone_width == 0.0f )
	{
		for( itr = m_caster->GetInRangeSetBegin(); itr != m_caster->GetInRangeSetEnd();)
		{
			itr2 = itr;
			itr++;
			if(!((*itr2)->IsUnit()) || !TO_UNIT(*itr2)->isAlive())
				continue;
			//is Creature in range
			if(m_caster->isInRange((*itr2),GetDBCCastTime(i)))
			{
				if(m_caster->isInFront(*itr2))
				{
					if(isAttackable(u_caster, (*itr2)))
						_AddTarget(TO_UNIT(*itr2), i);
				}
			}
		}
	}
	else
	{
		for( itr = m_caster->GetInRangeSetBegin(); itr != m_caster->GetInRangeSetEnd();)
		{
			itr2 = itr;
			itr++;
			if(!((*itr2)->IsUnit()) || !TO_UNIT(*itr2)->isAlive())
				continue;
			//is Creature in range
			if(m_caster->isInArc(*itr2, m_spellInfo->cone_width))
			{
				if(m_caster->isInFront((*itr2)))
				{
					if(isAttackable(u_caster, (*itr2)))
						_AddTarget(TO_UNIT(*itr2), i);
				}
			}
		}
	}
}
Beispiel #10
0
void WorldSession::HandleAttackSwingOpcode( WorldPacket & recv_data )
{
	CHECK_INWORLD_RETURN;
	CHECK_PACKET_SIZE(recv_data, 8);
	uint64 guid;
	recv_data >> guid;

	if(!guid)
	{
		// does this mean cancel combat?
		HandleAttackStopOpcode(recv_data);
		return;
	}

	// AttackSwing
	DEBUG_LOG( "WORLD"," Recvd CMSG_ATTACKSWING Message" );

	if(GetPlayer()->IsPacified() || GetPlayer()->IsStunned() || GetPlayer()->IsFeared())
		return;

//	printf("Got ATTACK SWING: %08X %08X\n", GUID_HIPART(guid), GUID_LOPART(guid));
	Unit* pEnemy = _player->GetMapMgr()->GetUnit(guid);
	//printf("Pointer: %08X\n", pEnemy);

	if(!pEnemy)
	{
		OUT_DEBUG("WORLD: "I64FMT" does not exist.", guid);
		return;
	}

	if(pEnemy->isDead() || _player->isDead())		// haxors :(
		return;

	// Faction "Hack" by Deathshit
	if( !isAttackable( GetPlayer(), pEnemy, false ) && !pEnemy->IsInRangeOppFactSet(_player) && !pEnemy->CombatStatus.DidDamageTo(GetPlayer()->GetGUID()))
	{
		GetPlayer()->BroadcastMessage("Faction exploit detected. You will be disconnected in 5 seconds.");
		GetPlayer()->Kick(5000);
		return;
	}

	GetPlayer()->smsg_AttackStart(pEnemy);
	GetPlayer()->EventAttackStart();

	// Set PVP Flag.
	/*if(pEnemy->IsPlayer() && isHostile(_player, pEnemy))
	{
		// don't in duel.. this should be done in dealdamage anyway :S
		if( TO_PLAYER( pEnemy )->GetTeam() != _player->GetTeam() )
			_player->SetPvPFlag();
	}*/
}
Beispiel #11
0
		uint8 CanCast(bool tolerate)
		{
			uint8 result = Spell::CanCast(tolerate);

			if(result == SPELL_CANCAST_OK)
			{
				if(m_caster != NULL && m_caster->IsInWorld())
				{
					Unit* target = m_caster->GetMapMgr()->GetUnit(m_targets.m_unitTarget);

					if(target == NULL || !(isAttackable(m_caster, target, false) || target->getRace() == RACE_UNDEAD))
						result = SPELL_FAILED_BAD_TARGETS;
				}
			}

			return result;
		}
Beispiel #12
0
/// Spell Target Handling for type 25: Single Target Friend	 // Used o.a. in Duel
void Spell::SpellTargetSingleFriend(uint32 i, uint32 j)
{
	if( !m_caster->IsInWorld() )
		return;
	TargetsList* tmpMap=&m_targetUnits[i];
	Unit *target = m_caster->GetMapMgr()->GetUnit((uint32)m_targets.m_unitTarget);
	if( target != NULL && isAttackable(u_caster, target) )
	{
		uint8 did_hit_result = DidHit(i,target);
		if(did_hit_result==SPELL_DID_HIT_SUCCESS)
			SafeAddTarget(tmpMap, m_targets.m_unitTarget);
		else
			SafeAddModeratedTarget(m_targets.m_unitTarget, did_hit_result);
	}
	else
	{
		SafeAddTarget(tmpMap,m_targets.m_unitTarget);
	}
}
Beispiel #13
0
/// Spell Target Handling for type 54: Targets in Front of the Caster
void Spell::SpellTargetInFrontOfCaster2(uint32 i, uint32 j)
{
	unordered_set<Object*>::iterator itr;

	for( itr = m_caster->GetInRangeSetBegin(); itr != m_caster->GetInRangeSetEnd(); ++itr )
	{
		if(!((*itr)->IsUnit()) || !TO_UNIT(*itr)->isAlive())
			continue;
		//is Creature in range
		if(m_caster->isInRange(TO_UNIT(*itr),GetDBCCastTime(i)))
		{
			if(m_caster->isInFront(TO_UNIT(*itr)))
			{
				if(isAttackable(u_caster, TO_UNIT(*itr)))
					_AddTarget(TO_UNIT(*itr), i);
			}
		}
	}
}
Beispiel #14
0
bool Starfall(uint32 i, Spell* pSpell)
{
    Unit* m_caster = pSpell->u_caster;
    if(m_caster == NULL)
        return true;
    uint8 am = 0;
    for(Object::InRangeSet::iterator itr = m_caster->GetInRangeSetBegin(); itr != m_caster->GetInRangeSetEnd(); ++itr)
    {
        if(!(*itr)->IsUnit())
            continue;
        Unit* Target = static_cast< Unit* >((*itr));
        if(isAttackable(Target, m_caster) && m_caster->CalcDistance((*itr)) <= pSpell->GetRadius(i))
        {
            m_caster->CastSpell(Target, pSpell->CalculateEffect(i, Target), true);
            ++am;
            if(am >= 2)
                return true;
        }
    }
    return true;
}
Beispiel #15
0
bool HolidayCheer(uint32 i, Spell *pSpell)
{
	if(!pSpell->m_caster) return true;

	Unit *target;
	float dist = pSpell->GetDBCCastTime(i);

	for(ObjectSet::iterator itr = pSpell->m_caster->GetInRangeSetBegin(); itr != pSpell->m_caster->GetInRangeSetEnd(); ++itr)
	{
		if((*itr)->IsUnit())
			target = TO_UNIT(*itr);
		else
			continue;

		if(pSpell->m_caster->CalcDistance(target) > dist || isAttackable(pSpell->m_caster, target))
			continue;

		target->Emote(EMOTE_ONESHOT_LAUGH);
	}
	return true;
}
bool DeathCoil(uint32 i, Spell* s)
{
	Unit* unitTarget = s->GetUnitTarget();

	if(s->p_caster == NULL || unitTarget == NULL)
		return false;

	int32 dmg = s->damage;

	if(isAttackable(s->p_caster, unitTarget, false))
	{
		s->p_caster->CastSpell(unitTarget, 47632, dmg, true);
	}
	else if(unitTarget->IsPlayer() && unitTarget->getRace() == RACE_UNDEAD)
	{
		dmg *= 1.5;
		s->p_caster->CastSpell(unitTarget, 47633, dmg, true);
	}

	return true;
}
Beispiel #17
0
void WorldSession::HandleAttackSwingOpcode(WorldPacket & recv_data)
{
	CHECK_INWORLD_RETURN

	CHECK_PACKET_SIZE(recv_data, 8);
	uint64 guid;
	recv_data >> guid;

	if(!guid)
	{
		// does this mean cancel combat?
		HandleAttackStopOpcode(recv_data);
		return;
	}

	// AttackSwing
	Log.Debug("WORLD", "Recvd CMSG_ATTACKSWING Message");

	if(GetPlayer()->IsPacified() || GetPlayer()->IsStunned() || GetPlayer()->IsFeared())
		return;

//	printf("Got ATTACK SWING: %08X %08X\n", GUID_HIPART(guid), Arcemu::Util::GUID_LOPART( guid ));
	Unit* pEnemy = _player->GetMapMgr()->GetUnit(guid);
	//printf("Pointer: %08X\n", pEnemy);

	if(!pEnemy)
	{
		LOG_DEBUG("WORLD: "I64FMT" does not exist.", guid);
		return;
	}

	if(pEnemy->IsDead() || _player->IsDead() || !isAttackable(_player, pEnemy, false))		// haxors :(
		return;

	GetPlayer()->smsg_AttackStart(pEnemy);
	GetPlayer()->EventAttackStart();

}
Beispiel #18
0
bool Starfall(uint8_t effectIndex, Spell* pSpell)
{
    Unit* m_caster = pSpell->u_caster;
    if (m_caster == NULL)
        return true;

    uint8 am = 0;
    for (const auto& itr : m_caster->getInRangeObjectsSet())
    {
        if (!itr || !itr->isCreatureOrPlayer())
            continue;

        Unit* Target = static_cast<Unit*>(itr);
        if (isAttackable(Target, m_caster) && m_caster->CalcDistance(itr) <= pSpell->GetRadius(effectIndex))
        {
            m_caster->castSpell(Target, pSpell->CalculateEffect(effectIndex, Target), true);
            ++am;
            if (am >= 2)
                return true;
        }
    }
    return true;
}
Beispiel #19
0
    void OnLoad()
    {
        if (_unit->IsPet())
        {
            Pet* s = TO< Pet* >(_unit);
            Player* owner = s->GetPetOwner();

            float owner_bonus = static_cast<float>(owner->GetDamageDoneMod(SCHOOL_SHADOW) * 0.375f); // 37.5%
            s->BaseAttackType = SCHOOL_SHADOW; // Melee hits are supposed to do damage with the shadow school
            s->SetBaseAttackTime(MELEE, 1500); // Shadowfiend is supposed to do 10 attacks, sometimes it can be 11
            s->SetMinDamage(s->GetMinDamage() + owner_bonus);
            s->SetMaxDamage(s->GetMaxDamage() + owner_bonus);
            s->BaseDamage[0] += owner_bonus;
            s->BaseDamage[1] += owner_bonus;

            Unit* uTarget = s->GetMapMgr()->GetUnit(owner->GetTargetGUID());
            if ((uTarget != NULL) && isAttackable(owner, uTarget))
            {
                s->GetAIInterface()->AttackReaction(uTarget, 1);
                s->GetAIInterface()->setNextTarget(uTarget);
            }
        }
    }
Beispiel #20
0
void WorldSession::HandleAttackSwingOpcode( WorldPacket & recv_data )
{	/*Apply a bugfix to prevent players from attacking people of the same faction. --Hemi*/
	if(!_player->IsInWorld()) return;
	CHECK_PACKET_SIZE(recv_data, 8);
	uint64 guid;
	recv_data >> guid;

	if(!guid)
	{	// does this mean cancel combat?
		HandleAttackStopOpcode(recv_data);
		return;
	}
	Log.Debug( "WORLD","Recvd CMSG_ATTACKSWING Message" );	// AttackSwing

	if(GetPlayer()->IsPacified() || GetPlayer()->IsStunned() || GetPlayer()->IsFeared())
		return;

	Unit *pEnemy = _player->GetMapMgr()->GetUnit(guid);
	if(!pEnemy)
	{
		sLog.outDebug("WORLD: "I64FMT" does not exist.", guid);
		return;
	}

	if(pEnemy->isDead() || _player->isDead())	// haxors :(
		return;

	bool attackablestatus = isAttackable( GetPlayer(), pEnemy, false );
	if( attackablestatus == false )
	{	//Prevent attacking people of the same faction. --Hemi
		HandleAttackStopOpcode(recv_data);
		return;
	}

	GetPlayer()->smsg_AttackStart(pEnemy);
	GetPlayer()->EventAttackStart();
}
Beispiel #21
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;
				}
			}
		}
	}
}
Beispiel #22
0
void DynamicObject::UpdateTargets()
{
	if(m_aliveDuration == 0)
		return;

	if(m_aliveDuration >= 100)
	{
		Unit* target;
		Aura* pAura;

		float radius = m_floatValues[ DYNAMICOBJECT_RADIUS ] * m_floatValues[ DYNAMICOBJECT_RADIUS ];

		// Looking for targets in the Object set
		for(std::set< Object* >::iterator itr = m_objectsInRange.begin(); itr != m_objectsInRange.end(); ++itr)
		{
			Object* o = *itr;

			if(!o->IsUnit() || !TO< Unit* >(o)->isAlive())
				continue;

			target = TO< Unit* >(o);

			if(!isAttackable(u_caster, target, !(m_spellProto->c_is_flags & SPELL_FLAG_IS_TARGETINGSTEALTHED)))
				continue;

			// skip units already hit, their range will be tested later
			if(targets.find(target->GetGUID()) != targets.end())
				continue;

			if(GetDistanceSq(target) <= radius)
			{
				pAura = sSpellFactoryMgr.NewAura(m_spellProto, m_aliveDuration, u_caster, target, true);
				for(uint32 i = 0; i < 3; ++i)
				{
					if(m_spellProto->Effect[i] == SPELL_EFFECT_PERSISTENT_AREA_AURA)
					{
						pAura->AddMod(m_spellProto->EffectApplyAuraName[i],
						              m_spellProto->EffectBasePoints[i] + 1, m_spellProto->EffectMiscValue[i], i);
					}
				}
				target->AddAura(pAura);
				if(p_caster)
				{
					p_caster->HandleProc(PROC_ON_CAST_SPECIFIC_SPELL | PROC_ON_CAST_SPELL, target, m_spellProto);
					p_caster->m_procCounter = 0;
				}

				// add to target list
				targets.insert(target->GetGUID());
			}
		}


		// loop the targets, check the range of all of them
		DynamicObjectList::iterator jtr  = targets.begin();
		DynamicObjectList::iterator jtr2;
		DynamicObjectList::iterator jend = targets.end();

		while(jtr != jend)
		{
			target = GetMapMgr() ? GetMapMgr()->GetUnit(*jtr) : NULL;
			jtr2 = jtr;
			++jtr;

			if((target != NULL) && (GetDistanceSq(target) > radius))
			{
				target->RemoveAura(m_spellProto->Id);
				targets.erase(jtr2);
			}
		}

		m_aliveDuration -= 100;
	}
	else
	{
		m_aliveDuration = 0;
	}

	if(m_aliveDuration == 0)
	{
		Remove();
	}
}
Beispiel #23
0
void DynamicObject::UpdateTargets()
{
	if(m_aliveDuration == 0)
		return;

	if(m_aliveDuration >= 100)
	{
		std::set<Object*>::iterator itr = GetInRangeSetBegin(),itr2;
		std::set<Object*>::iterator iend = GetInRangeSetEnd();
		Unit * target;
		Aura * pAura;
		float radius = m_floatValues[DYNAMICOBJECT_RADIUS]*m_floatValues[DYNAMICOBJECT_RADIUS];

		this->AquireInrangeLock(); //make sure to release lock before exit function !
		while(itr != iend)
		{
//			target = *itr;
//			++itr;

			itr2 = itr;
			++itr;

			if( !( (*itr2)->IsUnit() ) || ! static_cast< Unit* >( *itr2 )->isAlive() || ( static_cast< Creature* >( *itr2 )->IsTotem() && !static_cast< Unit* >( *itr2 )->IsPlayer() ) )
				continue;

			target = static_cast< Unit* >( *itr2 );

			if( !isAttackable( p_caster, target, !(m_spellProto->c_is_flags & SPELL_FLAG_IS_TARGETINGSTEALTHED) ) )
				continue;

			// skip units already hit, their range will be tested later
			if(targets.find(target->GetGUID()) != targets.end())
				continue;

			if(GetDistanceSq(target) <= radius)
			{
				pAura = AuraPool.PooledNew();
				pAura->Init(m_spellProto, m_aliveDuration, u_caster, target, true);
				for(uint32 i = 0; i < 3; ++i)
				{
					if(m_spellProto->Effect[i] == SPELL_EFFECT_PERSISTENT_AREA_AURA)
					{
						pAura->AddMod(m_spellProto->EffectApplyAuraName[i],
							m_spellProto->EffectBasePoints[i]+1, m_spellProto->EffectMiscValue[i], i);
					}
				}
				target->AddAura(pAura, m_spellScript);
				if(p_caster)
				{
					p_caster->HandleProc(PROC_ON_CAST_SPECIFIC_SPELL | PROC_ON_CAST_SPELL,target, m_spellProto);
					p_caster->m_procCounter = 0;
				}

				// add to target list
				targets.insert(target->GetGUID());
			}
		}

		this->ReleaseInrangeLock();
		// loop the targets, check the range of all of them
		DynamicObjectList::iterator jtr  = targets.begin();
		DynamicObjectList::iterator jtr2;
		DynamicObjectList::iterator jend = targets.end();
		
		while(jtr != jend)
		{
			target = GetMapMgr() ? GetMapMgr()->GetUnit(*jtr) : NULL;
			jtr2 = jtr;
			++jtr;

			if(GetDistanceSq(target) > radius)
			{
				target->RemoveAura(m_spellProto->Id);
				targets.erase(jtr2);
			}
		}

		m_aliveDuration -= 100;
	}
	else
	{
		m_aliveDuration = 0;
	}

	if(m_aliveDuration == 0)
	{
		Remove();
	}
}
Beispiel #24
0
void DynamicObject::UpdateTargets()
{
	if(m_aliveDuration == 0)
		return;

	if(m_aliveDuration >= 200)
	{
		Unit* target;

		float radius = m_floatValues[DYNAMICOBJECT_RADIUS]*m_floatValues[DYNAMICOBJECT_RADIUS];

		Object::InRangeSet::iterator itr,itr2;
		for( itr = GetInRangeSetBegin(); itr != GetInRangeSetEnd(); itr++)
		{
			itr2 = itr;

			if( !( (*itr2)->IsUnit() ) || ! TO_UNIT( *itr2 )->isAlive() || ((*itr2)->GetTypeId()==TYPEID_UNIT && TO_CREATURE(*itr2)->IsTotem() ) )
				continue;

			target = TO_UNIT( *itr2 );

			if( !isAttackable( m_caster, target, !(m_spellProto->c_is_flags & SPELL_FLAG_IS_TARGETINGSTEALTHED) ) )
				continue;

			// skip units already hit, their range will be tested later
			if(targets.find(target) != targets.end())
				continue;

			if(GetDistanceSq(target) <= radius)
			{
				Aura* pAura(new Aura(m_spellProto, m_aliveDuration, m_caster, target));

				for(uint32 i = 0; i < 3; ++i)
				{
					if(m_spellProto->Effect[i] == 27)
					{
						pAura->AddMod(m_spellProto->EffectApplyAuraName[i],
							m_spellProto->EffectBasePoints[i]+1, m_spellProto->EffectMiscValue[i], i);
					}
				}
				target->AddAura(pAura);
				if( m_caster->IsPlayer() )
				{
					p_caster->HandleProc(PROC_ON_CAST_SPECIFIC_SPELL | PROC_ON_CAST_SPELL,target, m_spellProto);
					p_caster->m_procCounter = 0;
				}

				// add to target list
				targets.insert(target);
			}
		}

		// loop the targets, check the range of all of them
		DynamicObjectList::iterator jtr  = targets.begin();
		DynamicObjectList::iterator jtr2;
		DynamicObjectList::iterator jend = targets.end();
		
		while(jtr != jend)
		{
			target = *jtr;
			jtr2 = jtr;
			++jtr;

			if(GetDistanceSq(target) > radius)
			{
				targets.erase(jtr2);
				target->RemoveAura(m_spellProto->Id);
			}
		}

		m_aliveDuration -= 200;
	}
	else
	{
		m_aliveDuration = 0;
	}

	if(m_aliveDuration == 0)
	{
		DynamicObjectList::iterator jtr  = targets.begin();
		DynamicObjectList::iterator jend = targets.end();
		Unit* target;

		while(jtr != jend)
		{
			target = *jtr;
			++jtr;
			target->RemoveAura(m_spellProto->Id);
		}
		Remove();
	}
}
Beispiel #25
0
bool Spell::AddTarget(uint32 i, uint32 TargetType, Object* obj)
{
	TargetsList* t = &m_targetUnits[i];

	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 && !isFriendly(m_caster, obj))
		return false;
	if(TargetType & SPELL_TARGET_REQUIRE_ATTACKABLE && !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;

	uint8 hitresult = TargetType & SPELL_TARGET_REQUIRE_ATTACKABLE && obj->IsUnit() ? DidHit(i, TO_UNIT(obj)) : SPELL_DID_HIT_SUCCESS;
	if(hitresult != SPELL_DID_HIT_SUCCESS)
	{
		uint8 extended = 0;
		if(hitresult == SPELL_DID_HIT_REFLECT && u_caster != NULL)
		{
			//for checks
			Unit* tmp = u_caster;
			u_caster = TO_UNIT(obj);
			extended = DidHit(i, tmp);
			u_caster = tmp;
		}
		ModeratedTargets.push_back(SpellTargetMod(obj->GetGUID(), hitresult));
		return false;
	}
	else
	{
		//check target isnt already in
		for(TargetsList::iterator itr = m_targetUnits[i].begin(); itr != m_targetUnits[i].end(); ++itr)
		{
			if(obj->GetGUID() == *itr)
				return false;
		}
		t->push_back(obj->GetGUID());
	}

	//final checks, require line of sight unless range/radius is 50000 yards
	SpellRange* r = dbcSpellRange.LookupEntry(m_spellInfo->rangeIndex);
	if(sWorld.Collision && r->maxRange < 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(!CollideInterface.CheckLOS(m_caster->GetMapId(), x, y, z + 2, obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ() + 2))
			return false;
	}



	return true;
}
Beispiel #26
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();
	}
}
///////////////////////////////////////////////////////////////////////
//Gnomish Shrink Ray dummy effect handler
//
//Preconditions
//  Casted by Player
//
//Effect
//  Normally casts spell 13010 on the targeted unit. Shrinking it, and
//  making it weaker
//
//  On malfunction it either shrinks, or enlarges, the the caster,
//  the caster's party, all enemies, or enlarges the target
//
//
//////////////////////////////////////////////////////////////////////
bool ShrinkRay(uint32 i, Spell* s)
{
	if(s->p_caster == NULL)
		return true;

	uint32 spellids[] =
	{
		13004, // grow
		13010  // shrink
	};

	uint32 chance =  RandomUInt(5);
	bool malfunction = false;

	if(chance == 5)
		malfunction = true;

	if(!malfunction)
	{

		s->p_caster->CastSpell(s->GetUnitTarget(), spellids[ 1 ], true);

	}
	else
	{
		uint32 spellindex = RandomUInt(1);
		uint32 who = RandomUInt(3);

		switch(who)
		{

			case 0:  // us
				{

					s->p_caster->CastSpell(s->p_caster, spellids[ spellindex ], true);

				}
				break;

			case 1:  // them
				{

					// if it's a malfunction it will only grow the target, since shrinking is normal
					s->p_caster->CastSpell(s->GetUnitTarget(), spellids[ 0 ], true);

				}
				break;

			case 2:  // our party
				{

					for(std::set< Object* >::iterator itr = s->p_caster->GetInRangePlayerSetBegin(); itr != s->p_caster->GetInRangePlayerSetEnd(); ++itr)
					{
						Player* p = TO_PLAYER(*itr);

						if((p->GetPhase() & s->p_caster->GetPhase()) == 0)
							continue;

						if(p->GetGroup()->GetID() != s->p_caster->GetGroup()->GetID())
							continue;

						s->p_caster->CastSpell(p, spellids[ spellindex ], true);
					}

				}
				break;

			case 3:  // every attacking enemy
				{

					for(std::set< Object* >::iterator itr = s->p_caster->GetInRangeOppFactsSetBegin(); itr != s->p_caster->GetInRangeOppFactsSetEnd(); ++itr)
					{
						Object* o = *itr;

						if((o->GetPhase() & s->p_caster->GetPhase()) == 0)
							continue;

						if(!o->IsCreature())
							continue;

						Unit* u = TO_UNIT(o);

						if(u->GetTargetGUID() != s->p_caster->GetGUID())
							continue;

						if(!isAttackable(s->p_caster, u))
							continue;

						s->p_caster->CastSpell(u, spellids[ spellindex ], true);
					}

				}
				break;
		}
	}

	return true;
}
Beispiel #28
0
void CUser::Attack(Packet & pkt)
{
	int16 sid = -1, tid = -1, damage, delaytime, distance;	
	uint8 bType, bResult = 0;	
	Unit * pTarget = nullptr;

	pkt >> bType >> bResult >> tid >> delaytime >> distance;

	//	delaytime = delaytime / 100.0f;
	//	distance = distance / 10.0f;

	if (isIncapacitated())
		return;

	if (isInSafetyArea())
		return;

	if (m_bInvisibilityType != INVIS_NONE)
	{
		CMagicProcess::RemoveStealth(this, INVIS_DISPEL_ON_MOVE);
		CMagicProcess::RemoveStealth(this, INVIS_DISPEL_ON_ATTACK);
	}

	// If you're holding a weapon, do a client-based (ugh, do not trust!) delay check.
	_ITEM_TABLE *pTable = GetItemPrototype(RIGHTHAND);
	if (pTable != nullptr) 
	{
		if (delaytime < (pTable->m_sDelay + 10) // client adds 0.1 onto the interval (0.1 of 100 is 10)
			|| distance > pTable->m_sRange)
			return;	
	}
	// Empty handed.
	else if (delaytime < 100)
		return;			

	pTarget = g_pMain->GetUnitPtr(tid);
	bResult = ATTACK_FAIL;

	if (pTarget != nullptr 
		&& isInAttackRange(pTarget)
		&& CanAttack(pTarget))
	{
		if (isAttackable(pTarget) && CanCastRHit(GetSocketID()))
		{
			if (isInTempleEventZone())
				if (GetUserGroup() != -1 && !isSameUserGroup(pTarget))
					return;

			CUser *pUser = g_pMain->GetUserPtr(GetSocketID());
			if (pUser != nullptr)
				pUser->m_RHitRepeatList.insert(std::make_pair(GetSocketID(), UNIXTIME));

			damage = GetDamage(pTarget);

			// Can't use R attacks in the Snow War.
			if (GetZoneID() == ZONE_SNOW_BATTLE 
				&& g_pMain->m_byBattleOpen == SNOW_BATTLE)
				damage = 0;

			if (damage > 0)
			{
				pTarget->HpChange(-damage, this);
				if (pTarget->isDead())
					bResult = ATTACK_TARGET_DEAD;
				else
					bResult = ATTACK_SUCCESS;

				// Every attack takes a little of your weapon's durability.
				ItemWoreOut(ATTACK, damage);

				// Every hit takes a little of the defender's armour durability.
				if (pTarget->isPlayer())
					TO_USER(pTarget)->ItemWoreOut(DEFENCE, damage);
			}
		}
	}

	Packet result(WIZ_ATTACK, bType);
	result << bResult << GetSocketID() << tid;
	SendToRegion(&result);
}
Beispiel #29
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();
	}
}
Beispiel #30
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;
				}
			}
		}
	}
}