float CGameRulesRSSpawning::GetScoreFromProximityToFriendlies(	SUsefulSpawnData& spawnData, TPositionList& FriendlyPlayerPositions,
																																TMultiplierList& FriendlyScoreMultipliers, const Vec3& potentialSpawnPosition )
{
	SpawnLogAlways("[SPAWN] > GetScoreFromProximityToFriendlies()");

	float	fScoreFromFriendlies = 0.0f;

	if(spawnData.numActiveFriendlyPlayers > 0)
	{
		const float fIdealMax = 30.0f;
		const float fIdealMin = 15.0f;

		const float fCloseFriendlyScoreMultiplier = 500.0f;
		const float fFarFriendlyScoreMultiplier		= 2.0f;

		float fClosestFriendlySq = FLT_MAX;
		int index = 0;

		for(int i = FriendlyPlayerPositions.size() - 1; i >= 0; i--)
		{
			Vec3 diff = (FriendlyPlayerPositions[i] - potentialSpawnPosition);
			
			//This will bias against using spawn positions near in X/Y but on a different level in Z
			float fZBiasDistanceFromFriendlySq = (diff.x * diff.x) + (diff.y * diff.y) + fabsf(diff.z * diff.z * diff.z);

			if(fZBiasDistanceFromFriendlySq < fClosestFriendlySq)
			{
				fClosestFriendlySq = fZBiasDistanceFromFriendlySq;
				index = i;
			}
		}

		float fClosestFriendly = sqrt_fast_tpl(fClosestFriendlySq);

		if(fClosestFriendly < fIdealMin)
		{	
			const float fAbortDist = 0.7f; //If the sapwn is within this distance of a friendly, we're going to be intersecting - abort
			const float fDiff = (fIdealMin - fClosestFriendly);
			const float fDistanceScore = (float)__fsel(fDiff - fAbortDist, fDiff, sqr(fDiff) * 10.0f);
			fScoreFromFriendlies =  fDiff * fCloseFriendlyScoreMultiplier * FriendlyScoreMultipliers[index];
		}
		else
		{
			const float fIdealSub = (fIdealMin + fIdealMax) * 0.5f;
			const float fIdealRadius = fabsf(fIdealMax - fIdealSub);
			fScoreFromFriendlies = max(fabsf(fClosestFriendly - fIdealSub) - fIdealRadius, 0.0f) * fFarFriendlyScoreMultiplier;
		}

		SpawnLogAlways("[SPAWN] >> Total Score from Friendlies: %.6f, closest was at %.2f, spawn time modifier %s", fScoreFromFriendlies, fClosestFriendly, FriendlyScoreMultipliers[index] < 1.0f ? "APPLIED" : "NOT APPLIED");
	}
	
	return fScoreFromFriendlies;
}
Ejemplo n.º 2
0
//------------------------------------------------------------------------
void CProjectile::HandleEvent(const SGameObjectEvent &event)
{
	if(m_destroying)
		return;

	FUNCTION_PROFILER(GetISystem(), PROFILE_GAME);

	if(event.event == eGFE_OnCollision)
	{
		EventPhysCollision *pCollision = (EventPhysCollision *)event.ptr;

		if(pCollision == NULL)
			return;

		const SCollisionParams *pCollisionParams = m_pAmmoParams->pCollision;

		if(pCollisionParams)
		{
			if(pCollisionParams->pParticleEffect)
				pCollisionParams->pParticleEffect->Spawn(true, IParticleEffect::ParticleLoc(pCollision->pt, pCollision->n, pCollisionParams->scale));

			if(pCollisionParams->sound)
			{
				_smart_ptr<ISound> pSound = gEnv->pSoundSystem->CreateSound(pCollisionParams->sound, FLAG_SOUND_DEFAULT_3D);

				if(pSound)
				{
					pSound->SetSemantic(eSoundSemantic_Projectile);
					pSound->SetPosition(pCollision->pt);
					pSound->Play();
				}
			}
		}

		// add battledust for bulletimpact
		if(gEnv->bServer && g_pGame->GetGameRules())
		{
			if(CBattleDust *pBD = g_pGame->GetGameRules()->GetBattleDust())
			{
				pBD->RecordEvent(eBDET_ShotImpact, pCollision->pt, GetEntity()->GetClass());
			}
		}

		Ricochet(pCollision);

		//Update damage
		if((m_damageDropPerMeter>0.0001f)&&
				(((pCollision->pt-m_initial_pos).len2()>m_damageDropMinDisSqr)||m_firstDropApplied))
		{

			if(!m_firstDropApplied)
			{
				m_firstDropApplied = true;
				m_initial_pos = m_initial_pos + (m_initial_dir*(sqrt_fast_tpl(m_damageDropMinDisSqr)));
			}

			Vec3 vDiff = pCollision->pt - m_initial_pos;
			float dis  = vDiff.len();

			m_damage -= (int)(floor_tpl(m_damageDropPerMeter * dis));

			//Check m_damage is positive
			if(m_damage<MIN_DAMAGE)
				m_damage=MIN_DAMAGE;

			//Also modify initial position (the projectile could not be destroyed, cause of pirceability)
			m_initial_pos = pCollision->pt;
		}

		// Notify AI system about grenades.
		if(gEnv->pAISystem)
		{
			IAIObject *pAI = 0;

			if((pAI = GetEntity()->GetAI()) != NULL && pAI->GetAIType() == AIOBJECT_GRENADE)
			{
				// Associate event with vehicle if the shooter is in a vehicle (tank cannon shot, etc)
				EntityId ownerId = m_ownerId;
				IActor *pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(ownerId);

				if(pActor && pActor->GetLinkedVehicle() && pActor->GetLinkedVehicle()->GetEntityId())
					ownerId = pActor->GetLinkedVehicle()->GetEntityId();

				SAIStimulus stim(AISTIM_GRENADE, AIGRENADE_COLLISION, ownerId, GetEntityId(),
								 GetEntity()->GetWorldPos(), ZERO, 12.0f);
				gEnv->pAISystem->RegisterStimulus(stim);
			}
		}
	}
}