Esempio n. 1
0
void CSmokeManager::CullOtherSmokeEffectsInProximityWhenGrenadeHasLanded(SSmokeInstance& smokeInstance, IEntity* pGrenade)
{
    if(pGrenade && (smokeInstance.state == eSIS_Active_PhysicsAwake))
        {
            IPhysicalEntity* pPhysEnt = pGrenade->GetPhysics();
            if(pPhysEnt)
                {
                    pe_status_awake psa;
                    if(pPhysEnt->GetStatus(&psa) == false)
                        {
                            // Was awake, now asleep...
                            SSmokeInstance* pOldestSmokeInstanceToDelete = NULL;
                            const int kNumActiveSmokeInstances = m_numActiveSmokeInstances;
                            uint32 otherSmokeInstanceProximityCount = 0;
                            SSmokeInstance* pOtherSmokeInstance = NULL;

                            PrefetchLine(m_smokeInstances, 0);
                            PrefetchLine(m_smokeInstances, 128);

                            // Find oldest smoke grenade effect in proximity
                            for(int i=0; i<kNumActiveSmokeInstances; i++)
                                {
                                    pOtherSmokeInstance = &m_smokeInstances[i];

                                    if(pOtherSmokeInstance != &smokeInstance)
                                        {
                                            PrefetchLine(pOtherSmokeInstance, 128);

                                            const float fDistanceSq = Distance::Point_PointSq(smokeInstance.vPositon, pOtherSmokeInstance->vPositon);

                                            const float fCombinedRadiusSq = sqr(smokeInstance.fMaxRadius) + sqr(pOtherSmokeInstance->fMaxRadius);
                                            if(fDistanceSq < fCombinedRadiusSq)
                                                {
                                                    otherSmokeInstanceProximityCount++;
                                                    if(pOldestSmokeInstanceToDelete == NULL || (pOldestSmokeInstanceToDelete->fTimer < pOtherSmokeInstance->fTimer))
                                                        {
                                                            pOldestSmokeInstanceToDelete = pOtherSmokeInstance;
                                                        }
                                                }
                                        }
                                }

                            // Delete old smoke effect in proximity if there are too many
                            if(pOldestSmokeInstanceToDelete && (otherSmokeInstanceProximityCount >= kMaxSmokeEffectsInSameArea))
                                {
                                    IEntity * pGrenadeToDeleteParticleEmitterFor = gEnv->pEntitySystem->GetEntity(pOldestSmokeInstanceToDelete->grenadeId);
                                    if(pGrenadeToDeleteParticleEmitterFor)
                                        {
                                            int slotCount = pGrenadeToDeleteParticleEmitterFor->GetSlotCount();
                                            for(int i=0; i<slotCount; i++)
                                                {
                                                    IParticleEmitter* pParticleEmitter = pGrenadeToDeleteParticleEmitterFor->GetParticleEmitter(i);
                                                    if(pParticleEmitter)
                                                        {
                                                            pParticleEmitter->Activate(false);
                                                        }
                                                }
                                        }
                                    pOldestSmokeInstanceToDelete->state = eSIS_ForDeletion;
                                }

                            smokeInstance.state = eSIS_Active_PhysicsAsleep;
                        }
                }
        }
}
//------------------------------------------------------------------------
void CTracerManager::Update(float frameTime)
{
	CryPrefetch(m_tracerPool);

	const CCamera& viewCamera = gEnv->pSystem->GetViewCamera();
	const Vec3 cameraPosition = viewCamera.GetPosition();
	const float viewCameraFovScale = viewCamera.GetFov() / DEG2RAD(g_pGame->GetFOV());

	const int kNumActiveTracers = m_numActiveTracers;

	for(int i = 0; i < kNumActiveTracers;)
	{
		int nextTracerIndex = i + 1;
		CTracer& tracer = m_tracerPool[i];
		CryPrefetch(&m_tracerPool[nextTracerIndex]);
		
		//Update
		const bool stillMoving = tracer.Update(frameTime, cameraPosition, viewCameraFovScale);

		//Is it worth putting this in another loop for instruction cache coherency? Profile when PS3 is up and running - Rich S
		if(stillMoving || (tracer.m_fadeOutTime > 0.f))
		{
			tracer.m_tracerFlags |= kTracerFlag_active;
			
			if (!stillMoving)
			{
				tracer.m_fadeOutTime -= frameTime;

				if (tracer.m_effectSlot > -1)
				{
					if (IEntity *pEntity = gEnv->pEntitySystem->GetEntity(tracer.m_entityId))
					{
						IParticleEmitter * emitter = pEntity->GetParticleEmitter(tracer.m_effectSlot);
						if (emitter)
						{
							emitter->Activate(false);
						}

						if (tracer.m_tracerFlags & kTracerFlag_useGeometry)
						{
							pEntity->SetSlotFlags(tracer.m_geometrySlot, pEntity->GetSlotFlags(tracer.m_geometrySlot) &~ (ENTITY_SLOT_RENDER|ENTITY_SLOT_RENDER_NEAREST));
						}

						tracer.m_effectSlot = -1;
					}
				}

				if(tracer.m_tracerFlags & kTracerFlag_useGeometry)
				{
					// Fade out geometry
					if((tracer.m_fadeOutTime < tracer.m_startFadeOutTime) && (tracer.m_startFadeOutTime > 0.0f))
					{
						if (IEntity *pEntity = gEnv->pEntitySystem->GetEntity(tracer.m_entityId))
						{
							IEntityRenderProxy *pRenderProxy = (IEntityRenderProxy*)pEntity->GetProxy(ENTITY_PROXY_RENDER);
							pRenderProxy->SetOpacity(max((tracer.m_fadeOutTime / tracer.m_startFadeOutTime) * tracer.m_geometryOpacity, 0.0f));
						}
					}
				}
			}
		}
		else
		{
			tracer.m_tracerFlags &= ~kTracerFlag_active;
			tracer.m_boundToBulletId = 0;
		}

		i = nextTracerIndex;
	}

	//This is where we clear out the inactive tracers, so the counter isn't const
	int numActiveTracers = kNumActiveTracers;
	
	CWeaponSystem* pWeaponSystem = g_pGame->GetWeaponSystem();

	for(int i = kNumActiveTracers - 1; i >= 0;)
	{
		int nextIndex = i - 1;
		CTracer& tracer = m_tracerPool[i];
		CryPrefetch(&m_tracerPool[nextIndex]);
		
		if(!(tracer.m_tracerFlags & kTracerFlag_active))
		{
			if (IEntity *pEntity=gEnv->pEntitySystem->GetEntity(tracer.m_entityId))
			{
				pEntity->Hide(true);
				pEntity->FreeSlot(TRACER_GEOM_SLOT);
				pEntity->FreeSlot(TRACER_FX_SLOT); 
			}

			//Switch the inactive tracer so it's at the end of the array;
			const int lastTracer = numActiveTracers - 1;
			static CTracer temp;
			temp = tracer;			
			numActiveTracers = lastTracer;
			tracer = m_tracerPool[lastTracer];
			m_tracerPool[lastTracer] = temp;

			//Re-bind index to the corresponding bullet
			if (tracer.m_boundToBulletId)
			{
				CProjectile* pProjectile = pWeaponSystem->GetProjectile(tracer.m_boundToBulletId);
				if (pProjectile && pProjectile->IsAlive())
				{
					if(lastTracer == pProjectile->GetTracerIdx())
					{
						pProjectile->BindToTracer(i);
					}
					else if(lastTracer == pProjectile->GetThreatTrailTracerIdx())
					{
						pProjectile->BindToThreatTrailTracer(i);
					}
				}
			}

		}

		i = nextIndex;
	}

	m_numActiveTracers = numActiveTracers;
}