CForceFeedBackSystem::SFFOutput CForceFeedBackSystem::SActiveEffect::Update( float frameTime )
{
	SFFOutput effectFF;

	bool canPlay = (runtimeParams.delay <= 0.0f);

	if (canPlay)
	{
		bool isLoopingEffect = (effectTime <= 0.0f); 

		const float effectTimeInv = !isLoopingEffect ? (float)__fres(effectTime) : 1.0f;
		const float sampleTime = runningTime * effectTimeInv;

		const float sampleTimeAAtFreq = sampleTime * frequencyA;
		const float sampleTimeAAtFreqNorm = clamp_tpl(sampleTimeAAtFreq - floor_tpl(sampleTimeAAtFreq), 0.0f, 1.0f);

		const float sampleTimeBAtFreq = sampleTime * frequencyB;
		const float sampleTimeBAtFreqNorm = clamp_tpl(sampleTimeBAtFreq - floor_tpl(sampleTimeBAtFreq), 0.0f, 1.0f);

		effectFF.forceFeedbackA = m_patternA.SamplePattern(sampleTimeAAtFreqNorm) * m_envelopeA.SampleEnvelope(sampleTime) * runtimeParams.intensity;
		effectFF.forceFeedbackB = m_patternB.SamplePattern(sampleTimeBAtFreqNorm) * m_envelopeB.SampleEnvelope(sampleTime) * runtimeParams.intensity;
		runningTime += frameTime;

		//Re-start the loop
		if (isLoopingEffect)
		{
			runningTime = (float)__fsel(1.0f - runningTime, runningTime, 0.0f);
		}
	}
	else
	{
		runtimeParams.delay = clamp_tpl(runtimeParams.delay - frameTime, 0.0f, runtimeParams.delay);
	}


	return effectFF;
}
Exemple #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);
			}
		}
	}
}
//------------------------------------------------------------------------
void CGameRulesMPDamageHandling::SvOnExplosion(const ExplosionInfo &explosionInfo, const CGameRules::TExplosionAffectedEntities& affectedEntities)
{
	// SinglePlayer.lua 1721

	IActorSystem* pActorSystem = g_pGame->GetIGameFramework()->GetIActorSystem();
	float totalDamage = 0.f;

	// calculate damage for each entity
	CGameRules::TExplosionAffectedEntities::const_iterator it = affectedEntities.begin();
	for (; it != affectedEntities.end(); ++it)
	{
		bool success = false;
		IEntity* entity = it->first;
		float obstruction = 1.0f - it->second;

		bool incone=true;
		if (explosionInfo.angle > 0 && explosionInfo.angle < 2*3.1415f)
		{
			Vec3 explosionEntityPos = entity->GetWorldPos();
			Vec3 entitypos = explosionEntityPos;
			float ha = explosionInfo.angle * 0.5f;
			Vec3 edir = entitypos - explosionInfo.pos;
			edir.normalize();
			float dot = 1;

			if (edir != Vec3(ZERO))
			{
				dot = edir.dot(explosionInfo.dir);
			}

			float angle = abs(acos_tpl(dot));
			if (angle > ha)
			{
				incone = false;
			}
		}

		if (incone && gEnv->bServer)
		{
			float damage = explosionInfo.damage;
			damage = floor_tpl(0.5f + CalcExplosionDamage(entity, explosionInfo, obstruction));	

			bool dead = false;

			HitInfo explHit;

			Vec3 dir = entity->GetWorldPos() - explosionInfo.pos;

			explHit.pos = explosionInfo.pos;
			explHit.radius = explosionInfo.radius;
			explHit.partId = -1;

			dir.Normalize();

			explHit.targetId = entity->GetId();
			explHit.weaponId = explosionInfo.weaponId;
			explHit.shooterId = explosionInfo.shooterId;
			explHit.projectileId = explosionInfo.projectileId;
			explHit.projectileClassId = explosionInfo.projectileClassId;

			uint16 weaponClass = ~uint16(0);
			const IEntity* pWeaponEntity = gEnv->pEntitySystem->GetEntity(explosionInfo.weaponId);
			if (pWeaponEntity)
			{
				g_pGame->GetIGameFramework()->GetNetworkSafeClassId(weaponClass, pWeaponEntity->GetClass()->GetName());
			}
			explHit.weaponClassId = weaponClass;

			explHit.material = 0;
			explHit.damage = damage;
			explHit.type = explosionInfo.type;
			explHit.hitViaProxy = explosionInfo.explosionViaProxy;

			explHit.dir = dir;
			explHit.normal = -dir; //set normal to reverse of  direction to avoid backface cull of damage

			if (explHit.damage > 0.0f || explosionInfo.damage == 0.f)
			{
				CActor* pActor = static_cast<CActor*>(pActorSystem->GetActor(entity->GetId()));

				if (pActor)
				{
					const float damageMultiplier = pActor->GetBodyExplosionDamageMultiplier(explHit);
					explHit.damage *= damageMultiplier; 

					// Protect players who are currently shielded
					if(pActor->IsPlayer() && static_cast<CPlayer*>(pActor)->ShouldFilterOutExplosion(explHit))
					{
						explHit.damage = 0.0f;
					}
				}
				else
				{
					CInteractiveObjectEx* pInteractiveObject = static_cast<CInteractiveObjectEx*>(g_pGame->GetIGameFramework()->QueryGameObjectExtension(entity->GetId(), "InteractiveObjectEx"));
					if(pInteractiveObject)
					{
						pInteractiveObject->OnExploded(explHit.pos);
					}
				}
			
				if(!explosionInfo.explosionViaProxy) 
				{
					if(pActor)
					{
						if(!pActor->IsFriendlyEntity(explHit.shooterId))
						{
							totalDamage += damage;
						}
					}
					else
					{
						IVehicle* pVehicle = g_pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(entity->GetId());

						if(pVehicle)
						{
							IActor* pDriver = pVehicle->GetDriver();
							int seatNum = 0;
							int numSeats = pVehicle->GetSeatCount();

							while(!pDriver && seatNum < numSeats)
							{
								IVehicleSeat* pSeat = pVehicle->GetSeatById(seatNum++);

								EntityId passengerId = pSeat ? pSeat->GetPassenger(true) : 0;
								pDriver = pActorSystem->GetActor(passengerId);
							}

							if(pDriver)
							{
								CActor* pDriverActor = static_cast<CActor*>(pDriver);
								if(!pDriverActor->IsFriendlyEntity(explHit.shooterId))
								{
									totalDamage += damage;
								}
							}
						}
					}
				}
				
				m_pGameRules->ServerHit(explHit);
			}
		}
	}

	if (totalDamage > 0.f)
	{
		IGameRulesPlayerStatsModule*  pPlayStatsMod = m_pGameRules->GetPlayerStatsModule();

		if(pPlayStatsMod)
		{
			pPlayStatsMod->ProcessSuccessfulExplosion(explosionInfo.shooterId, totalDamage, explosionInfo.projectileClassId);
		}
	}
}