/* ----------------------------------------------------------------------------
Creates a particle emitter for an animated mesh scene node

Parameters:
 node,:  Pointer to the animated mesh scene node to emit particles from
 useNormalDirection,:  If true, the direction of each particle created will be
						the normal of the vertex that it's emitting from. The
						normal is divided by the normalDirectionModifier
						parameter, which defaults to 100.0f.
 direction,:  Direction and speed of particle emission.
 normalDirectionModifier,:  If the emitter is using the normal direction then the
							normal of the vertex that is being emitted from is
							divided by this number.
 mbNumber,:  This allows you to specify a specific meshBuffer for the IMesh* to
			emit particles from. The default value is -1, which means a random
			meshBuffer picked from all of the meshes meshBuffers will be selected
			to pick a random vertex from. If the value is 0 or greater, it will
			only pick random vertices from the meshBuffer specified by this value.
 everyMeshVertex,:  If true, the emitter will emit between min/max particles every
					second, for every vertex in the mesh, if false, it will emit
					between min/max particles from random vertices in the mesh.
 minParticlesPerSecond,:  Minimal amount of particles emitted per second.
 maxParticlesPerSecond,:  Maximal amount of particles emitted per second.
 minStartColor,:  Minimal initial start color of a particle. The real color of every
				particle is calculated as random interpolation between minStartColor
				and maxStartColor.
 maxStartColor,:  Maximal initial start color of a particle. The real color of every
				particle is calculated as random interpolation between minStartColor
				and maxStartColor.
 lifeTimeMin,:  Minimal lifetime of a particle, in milliseconds.
 lifeTimeMax,:  Maximal lifetime of a particle, in milliseconds.
 maxAngleDegrees,:  Maximal angle in degrees, the emitting direction of the particle
					will differ from the orignial direction.

Returns:
Returns a pointer to the created particle emitter. To set this emitter as new
emitter of this particle system, just call setEmitter(). Note that you'll have
to drop() the returned pointer, after you don't need it any more, see
IReferenceCounted::drop() for more informations.
*/
IParticleEmitter * DLL_EXPORT IrrAddAnimatedMeshSceneNodeEmitter (
		IParticleSystemSceneNode* ps,
		IAnimatedMeshSceneNode* node,
		bool useNormalDirection,
		float normalDirectionModifier,
		bool emitFromEveryMeshVertex,
		IRR_PARTICLE_EMITTER prop )
{
	IParticleEmitter* em = ps->createAnimatedMeshSceneNodeEmitter(
			node,
			useNormalDirection,
			core::vector3df(prop.direction_x,prop.direction_y,prop.direction_z),
			normalDirectionModifier,
			-1,	// use a random meshbuffer from within the node
			emitFromEveryMeshVertex,
			prop.min_paritlcles_per_second,prop.max_paritlcles_per_second,
			video::SColor(0,prop.min_start_color_red,prop.min_start_color_green,prop.min_start_color_blue),
			video::SColor(0,prop.max_start_color_red,prop.max_start_color_green,prop.max_start_color_blue),
			prop.min_lifetime,prop.max_lifetime,
			prop.max_angle_degrees );

    em->setMinStartSize( dimension2d<f32>(prop.min_start_sizeX, prop.min_start_sizeY));
    em->setMaxStartSize( dimension2d<f32>(prop.max_start_sizeX, prop.max_start_sizeY));
	ps->setEmitter(em);
	em->drop();
	return em;
}
Beispiel #2
0
Explosion::Explosion(const core::vector3df& position) : Effect(EXPLOSIONLENGTH), fireParticles(0), shockwave(0)
{
	//intialize particle system
	sound->play3D("res/sounds/reactor_explo.wav", position);
	fireParticles = scenemngr->addParticleSystemSceneNode(false, 0, -1, position);
	IParticleEmitter *emitter = fireParticles->createSphereEmitter(vector3df(0,0,0), 20,
		vector3df(0,0,0), 100, 200, video::SColor(0,255,255,255), video::SColor(0,255,255,255),
		2000, 4000, 0, dimension2df(75,75), dimension2df(150,150));
	fireParticles->setEmitter(emitter);

	fireParticles->setMaterialTexture(0, vdriver->getTexture("res/textures/engine_trails.pcx"));
	fireParticles->setMaterialFlag(video::EMF_LIGHTING, false);
	fireParticles->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);

	IParticleAffector *af = fireParticles->createAttractionAffector(position, -100.f);
	fireParticles->addAffector(af);
	emitter->drop();
	af->drop();

	shockwave = scenemngr->addCubeSceneNode(5);
	shockwave->setScale(core::vector3df(5,0,5));
	shockwave->setMaterialTexture(0,vdriver->getTexture("res/textures/fx/shockwave.png"));
	shockwave->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL);
	shockwave->setPosition(position);
	shockwave->setMaterialFlag(video::EMF_LIGHTING, false);

}
// ============================================================================
//	Show the effect at a position (this will spawn the particle emitter if 
//	needed).
//
//	In:		The world-space position of the effect.
//
void CPlayerMindGameBeamEffectSimpleEffect::SetPosition(const Vec3& pos)
{
	IParticleEmitter* emitter = GetParticleEmitter(pos);
	if (emitter == NULL)
	{
		return;
	}

	Matrix34 matrix = Matrix34::CreateTranslationMat(pos);
	emitter->SetMatrix(matrix);
}
//------------------------------------------------------------------------
void CGameRulesHoldObjectiveBase::RadiusEffectPulse(EntityId entityId, eRadiusPulseType pulseType, float fScale)
{
	IEntity* pEntity = gEnv->pEntitySystem->GetEntity(entityId);
	Vec3 entityPos(0.0f,0.0f,0.0f);
	if(pEntity)
	{
		entityPos = pEntity->GetPos();
		entityPos.z += 0.5f;
	}

	if (m_effectData.pParticleEffect)
	{
		float particleEffectScale = fScale*m_effectData.particleEffectScale;
		IParticleEmitter* pEmitter = m_effectData.pParticleEffect->Spawn(false, IParticleEffect::ParticleLoc(entityPos, Vec3(0.f, 0.f, 1.f), particleEffectScale));
		if(pEmitter)
		{
			SpawnParams spawnParams;
			pEmitter->GetSpawnParams(spawnParams);
			spawnParams.fStrength = m_effectData.particleColorLerp.GetValue();
			pEmitter->SetSpawnParams(spawnParams);
		}
	}

#ifndef _RELEASE
	if(g_pGameCVars->g_holdObjectiveDebug == eHOB_Debug_Fade_Ring_With_Pulse)
	{
		m_effectData.alphaLerp.Set(0.0f,0.0f,1.0f);
	}
#endif

	// Start ring geom fade-in
	if(m_effectData.alphaLerp.GetValue() == 0.0f)
	{
		m_effectData.alphaLerp.Set(0.0f,1.0f,0.0f);
		m_effectData.alphaFadeInDelay = m_effectData.alphaFadeInDelayDuration;

		IEntity *pRingEntity = gEnv->pEntitySystem->GetEntity(m_effectData.ringEntityID);
		if(pRingEntity)
		{
			float ringGeomScale = fScale * m_effectData.ringGeomScale;
			pRingEntity->SetPos(entityPos);
			pRingEntity->SetScale(Vec3(ringGeomScale,ringGeomScale,1.0f));

#ifndef _RELEASE
			if(g_pGameCVars->g_holdObjectiveDebug == eHOB_Debug_Fade_Ring_With_Pulse)
			{
				pRingEntity->Hide(true);
				SetRingAlpha(pRingEntity,0.0f);
			}
#endif
		}
	}
}
Beispiel #5
0
// Causes this object to explode, making it vanish, and return a particle
//	effect node animating the explosion effect in its current position.
void Soldier::createExplosionEffect(){
	// add a new explosion particle systems (for the two intermixed explosions)
    this->explosionParticleSystem =
		this->smgr->addParticleSystemSceneNode(false);
    this->explosionParticleSystemLarge =
        this->smgr->addParticleSystemSceneNode(false);
    
	// add an emitter for BLOODSPLOSION!!!!!!!!!!!!!!!
	IParticleEmitter *explosionEmitter =
	    this->explosionParticleSystem->createBoxEmitter(
		    aabbox3d<f32>(-5, 0, -5, 5, 1, 5),  // emitter size
		    vector3df(0.0f,0.0f,0.1f),          // direction + speed
		    2000, 5000,                       // min,max particles per second
		    SColor(0,255,255,255),              // darkest color
		    SColor(0,255,255,255),              // brightest color
		    200, 800,                          // min, max particle lifetime
		    360,                                // max angle degrees
		    dimension2df(40.0f, 40.0f),         // min start size
		    dimension2df(200.0f, 200.0f));        // max start size
	this->explosionParticleSystem->setEmitter(explosionEmitter);
	explosionEmitter->drop(); // drop (re-created later)
	
	//add gravity affector to BLOODSPLOSION!!!!!!!!!!!!
	IParticleGravityAffector* pgaf = explosionParticleSystem->createGravityAffector
											(vector3df(0.F,-0.2F,0.0F), 200U);
	explosionParticleSystem->addAffector(pgaf);
    pgaf->drop();

	// add fade-out affector to the BLOODSPLOSION!!!!!!!!!!!!
	IParticleAffector* explosionFadeOutAffector =
	    explosionParticleSystem->createFadeOutParticleAffector();
	this->explosionParticleSystem->addAffector(explosionFadeOutAffector);
	explosionFadeOutAffector->drop();
	
	// customize the particle system positioning, etc.
	vector3df explosionPos = this->sceneNode->getPosition();
	if(explosionPos.Y < 0) // adjust position: no explosions underground!
	    explosionPos.Y = 0;

	// adjust the blood
	this->explosionParticleSystem->setPosition(explosionPos);
	this->explosionParticleSystem->setScale(vector3df(45, 45, 45));
	this->explosionParticleSystem->setMaterialFlag(EMF_LIGHTING, false);
	this->explosionParticleSystem->setMaterialFlag(EMF_ZWRITE_ENABLE, false);
	this->explosionParticleSystem->setMaterialTexture(0,
	this->driver->getTexture("assets/textures/blood.bmp"));
	this->explosionParticleSystem->setMaterialType(EMT_TRANSPARENT_ADD_COLOR);
}
/* ----------------------------------------------------------------------------
create an emitter that can be added to a particle system
*/
IParticleEmitter * DLL_EXPORT IrrAddParticleEmitter( IParticleSystemSceneNode* ps, IRR_PARTICLE_EMITTER prop )
{
	IParticleEmitter* em = ps->createBoxEmitter(
		core::aabbox3d<f32>(prop.min_box_x,prop.min_box_y,prop.min_box_z,prop.max_box_x,prop.max_box_y,prop.max_box_z),
		core::vector3df(prop.direction_x,prop.direction_y,prop.direction_z),
		prop.min_paritlcles_per_second,prop.max_paritlcles_per_second,
		video::SColor(0,prop.min_start_color_red,prop.min_start_color_green,prop.min_start_color_blue),
		video::SColor(0,prop.max_start_color_red,prop.max_start_color_green,prop.max_start_color_blue),
		prop.min_lifetime,prop.max_lifetime,
		prop.max_angle_degrees );

    em->setMinStartSize( dimension2d<f32>(prop.min_start_sizeX, prop.min_start_sizeY));
    em->setMaxStartSize( dimension2d<f32>(prop.max_start_sizeX, prop.max_start_sizeY));
	ps->setEmitter(em);
	em->drop();
	return em;
}
Beispiel #7
0
bool CTornado::UseFunnelEffect(const char* effectName)
{
	m_pFunnelEffect = gEnv->pParticleManager->FindEffect(effectName);

	if (!m_pFunnelEffect)
		return false;

	// move particle slot to the helper position+offset
	GetEntity()->LoadParticleEmitter(0, m_pFunnelEffect, 0, false);
	Matrix34 tm(IDENTITY);
	GetEntity()->SetSlotLocalTM(0, tm);
	GetEntity()->SetSlotFlags(0, GetEntity()->GetSlotFlags(0)|ENTITY_SLOT_RENDER);
	IParticleEmitter* pEmitter = GetEntity()->GetParticleEmitter(0);
	assert(pEmitter);
	pEmitter->Prime();

	// init the first time
	if (!m_pCloudConnectEffect)
	{
		m_pCloudConnectEffect = gEnv->pParticleManager->FindEffect("weather.tornado.cloud_connection");
		if (m_pCloudConnectEffect)
		{
			GetEntity()->LoadParticleEmitter(1, m_pCloudConnectEffect, 0, true);
		}
	}
	if (!m_pTopEffect)
	{
		m_pTopEffect = gEnv->pParticleManager->FindEffect("weather.tornado.top_part");
		if (m_pTopEffect)
		{
			GetEntity()->LoadParticleEmitter(2, m_pTopEffect, 0, true);
		}
	}

	if (!m_pGroundEffect)
	{
		m_pGroundEffect = g_pGame->GetIGameFramework()->GetIEffectSystem()->CreateGroundEffect(GetEntity());
		m_pGroundEffect->SetParticleEffect("weather.tornado.leaves");
	}

	UpdateParticleEmitters();
	return true;
}
//! constructor
CParticleSystemSceneNode::CParticleSystemSceneNode(bool createDefaultEmitter,
	ISceneNode* parent, ISceneManager* mgr, s32 id,
	const core::vector3df& position, const core::vector3df& rotation,
	const core::vector3df& scale)
	: IParticleSystemSceneNode(parent, mgr, id, position, rotation, scale),
	Emitter(0), ParticleSize(core::dimension2d<f32>(5.0f, 5.0f)), LastEmitTime(0),
	MaxParticles(0xffff), Buffer(0), ParticlesAreGlobal(true)
{
	#ifdef _DEBUG
	setDebugName("CParticleSystemSceneNode");
	#endif

	Buffer = new SMeshBuffer();
	if (createDefaultEmitter)
	{
		IParticleEmitter* e = createBoxEmitter();
		setEmitter(e);
		e->drop();
	}
}
//! constructor
CParticleSystemSceneNode::CParticleSystemSceneNode(bool createDefaultEmitter,
	ISceneNode* parent, ISceneManager* mgr, s32 id, 
	const core::vector3df& position, const core::vector3df& rotation,
	const core::vector3df& scale)
	: IParticleSystemSceneNode(parent, mgr, id, position, rotation, scale),
	Emitter(0), ParticlesAreGlobal(true)
{
	#ifdef _DEBUG
	setDebugName("CParticleSystemSceneNode");
	#endif

	if (createDefaultEmitter)
	{
		IParticleEmitter* e = createBoxEmitter();
		setEmitter(e);
		e->drop();
	}

	setParticleSize();
}
IParticleEmitter* EntityEffects::SpawnParticleFX( IParticleEffect* pParticleEffect, const EntityEffects::SEffectSpawnParams& spawnParams)
{
	if (pParticleEffect)
	{
		IParticleEmitter* pEmitter = pParticleEffect->Spawn(true, IParticleEffect::ParticleLoc(spawnParams.position, spawnParams.direction, spawnParams.scale));

		if (pEmitter != NULL && spawnParams.prime)
		{
			pEmitter->Prime();
		}

		if (spawnParams.speed > 0.0f)
		{
			ParticleParams particleParams = pParticleEffect->GetParticleParams();
			particleParams.fSpeed = spawnParams.speed;
			pParticleEffect->SetParticleParams(particleParams);
		}

		return pEmitter;
	}

	return NULL;
}
Beispiel #11
0
/******************************************************************************
 * Set the mood and visible state of the world to a light, happy "fabulous"
 * mode - bright pink sparkles lightly fall from the sky.
 *****************************************************************************/
void GameInstance::setWorldState_fabulous() {
  // add a particle system effect to rain pink debree:
  if(this->rainParticleSystem)
    this->rainParticleSystem->drop();
  this->createRainParticleSystem("assets/textures/pinkfire.bmp");

  // add the rain emitter to the rain particle system
  IParticleEmitter *rainEmitter =
    this->rainParticleSystem->createBoxEmitter(
        aabbox3d<f32>(-100, 0, -100, 100, 100, 100),  // emitter size
        vector3df(0.0f, -0.5f, 0.0f),          // direction + speed
        100, 200,                       // min,max particles per second
        SColor(0,255,255,255),              // darkest color
        SColor(0,255,255,255),              // brightest color
        500, 3000,                       // min, max particle lifetime
        0,                                // max angle degrees
        dimension2df(20.0f, 20.0f),         // min start size
        dimension2df(60.0f, 60.0f));        // max start size
  this->setRainEmitter(rainEmitter);
  rainEmitter->drop();

  // set the ambiance to pretty
  this->light->setAmbientLight(255, 172, 253);
}
Beispiel #12
0
void CBurnEffectManager::CreateBurnEffect(const EventPhysCollision& pCollision, CBurnEffectManager::SBurnPoint* pBurnPoint)
{
	Vec3 surfaceNormal = pCollision.n;
	Vec3 hitDir(ZERO);
	if (pCollision.vloc[0].GetLengthSquared() > 1e-6f)
	{
		hitDir = pCollision.vloc[0].GetNormalized();
	}
	Vec3 surfacePosition = pCollision.pt;
	Vec3 halfVector = (surfaceNormal + (-hitDir)).GetNormalized();

	CItemParticleEffectCache& particleCache = g_pGame->GetGameSharedParametersStorage()->GetItemResourceCache().GetParticleEffectCache();
	IParticleEffect* pParticleEffect = particleCache.GetCachedParticle(pBurnPoint->m_pBurnParams->m_effectName);

	if (pParticleEffect)
	{
		Matrix34 loc;
		loc.SetIdentity();
		loc.SetTranslation(surfacePosition);
		loc.SetRotation33(OrthoNormalVector(surfaceNormal));
		IParticleEmitter* pEffect = pParticleEffect->Spawn(false, loc);
		if(pEffect)
		{
			pEffect->AddRef();
			pBurnPoint->m_effect = pEffect;

			const ParticleParams& particleParams = pParticleEffect->GetParticleParams();

			pBurnPoint->m_attachType = particleParams.eAttachType;
			pBurnPoint->m_attachForm = particleParams.eAttachForm;
		}
		UpdateBurnEffect(pBurnPoint);
	}
	
	UpdateBurnEffect(pBurnPoint);
}
Beispiel #13
0
    IParticleSystemSceneNode* IrrFactory::addParticleSystemNode( const std::string& particleSystemFile )
    {
        PropertyMap propMap;

        if( propMap.constructPropertyMap( SimFactory::TransformPath(particleSystemFile) ) )
        {
            // default values
            const vector3df pos( 0, 0, 0 );
            const vector3df rot( 0, 0, 0 );
            const vector3df scale( 1, 1, 1 );

            // create the particle system node
            IParticleSystemSceneNode* pSystem = mIrr.getSceneManager()->addParticleSystemSceneNode( false, 0, -1, pos, rot, scale );
            Assert( pSystem );

            // read some custom properties
            bool             globalMovement = true;
            dimension2df     particleSize( 5.0f, 5.0f );

            propMap.getValue( globalMovement, "ParticleSystem.System.GlobalMovement" );
            propMap.getValue( particleSize,   "ParticleSystem.System.ParticleSize" );

            pSystem->setParticlesAreGlobal(globalMovement);
            pSystem->setParticleSize(particleSize);

            /// ---- load the effectors ----

            // get the gravity properties
            if( propMap.hasSection( "ParticleSystem.Gravity" ) )
            {
                vector3df gravDir( 0, -1, 0 );
                uint32_t affectorTimeMS(1000);

                // try to read params
                propMap.getValue( gravDir,   "ParticleSystem.Gravity.Direction" );
                propMap.getValue( affectorTimeMS, "ParticleSystem.Gravity.AffectorTimeMS" );

                gravDir = ConvertNeroToIrrlichtPosition(gravDir);

                IParticleAffector* pGravity = pSystem->createGravityAffector( gravDir, affectorTimeMS );
                Assert( pGravity );

                pSystem->addAffector( pGravity );
                pGravity->drop();
            }

            // get the fade properties
            if( propMap.hasSection( "ParticleSystem.Fade" ) )
            {
                SColor targetColor(0,0,0,0);
                uint32_t affectorTimeMS(1000);

                // try to read params
                propMap.getValue( targetColor,  "ParticleSystem.Fade.TargetColor" );
                propMap.getValue( affectorTimeMS, "ParticleSystem.Fade.AffectorTimeMS" );

                IParticleAffector* pFade = pSystem->createFadeOutParticleAffector( targetColor, affectorTimeMS );
                Assert( pFade );

                pSystem->addAffector( pFade );
                pFade->drop();
            }


            // ---- load the emitters ----
            // --- NOTE: WE ONLY DO BOX EMITTERS ---

            if( propMap.hasSection( "ParticleSystem.Emitter" ) )
            {
                // default params
                aabbox3df box(-10, 28,-10, 10, 30, 10);
                vector3df dir( 0, .03f, 0 );
                uint32_t  minParticlesPerSecond = 5;
                uint32_t  maxParticlesPerSecond = 10;
                SColor    minStartColor( 255, 0, 0, 0 );
                SColor    maxStartColor( 255, 255, 255, 255 );
                uint32_t  lifeTimeMin = 2000;
                uint32_t  lifeTimeMax = 4000;
                int32_t   maxAngleDegrees = 0;

                // try to read custom params

                propMap.getValue( box,      "ParticleSystem.Emitter.Box" );
                propMap.getValue( dir,      "ParticleSystem.Emitter.Direction" );
                propMap.getValue( minParticlesPerSecond, "ParticleSystem.Emitter.MinParticlesPerSecond" );
                propMap.getValue( maxParticlesPerSecond, "ParticleSystem.Emitter.MaxParticlesPerSecond" );
                propMap.getValue( minStartColor,   "ParticleSystem.Emitter.MinStartColor" );
                propMap.getValue( maxStartColor,   "ParticleSystem.Emitter.MaxStartColor" );
                propMap.getValue( lifeTimeMin,    "ParticleSystem.Emitter.LifetimeMin" );
                propMap.getValue( lifeTimeMax,    "ParticleSystem.Emitter.LifetimeMax" );
                propMap.getValue( maxAngleDegrees,   "ParticleSystem.Emitter.MaxAngleDegrees" );

                // do coordinate system transformations
                dir = ConvertNeroToIrrlichtPosition(dir);

                // create the emitter
                IParticleEmitter* emit = pSystem->createBoxEmitter
                                         ( box,
                                           dir,
                                           minParticlesPerSecond,
                                           maxParticlesPerSecond,
                                           minStartColor,
                                           maxStartColor,
                                           lifeTimeMin,
                                           lifeTimeMax,
                                           maxAngleDegrees );
                Assert( emit );

                pSystem->setEmitter( emit );
                emit->drop();
            }
            else
            {
                LOG_F_WARNING( "render", "No emitter in particle system file - " << particleSystemFile );
            }

            return pSystem;
        }

        return NULL;
    }
Beispiel #14
0
void CSmokeManager::UpdateSmokeInstance(SSmokeInstance& smokeInstance, float dt)
{
    IEntity * pGrenade = gEnv->pEntitySystem->GetEntity(smokeInstance.grenadeId);

    CullOtherSmokeEffectsInProximityWhenGrenadeHasLanded(smokeInstance,pGrenade);

    if(pGrenade)
        {
            //Update the radius of the smoke according to the speed of movement,
            //	it should reduce to nothing when moving fast enough, and should increase
            //	when the grenade is stationary
            Vec3 vNewPosition		= pGrenade->GetPos();

            Vec3 vPositionDiff	= vNewPosition - smokeInstance.vPositon;

            const float fDistanceTravelled = vPositionDiff.len();

            const float fSpeed = fDistanceTravelled * __fres(dt);

            const float fNewRadius = smokeInstance.fCurrentRadius + (float)__fsel( smokeInstance.fTimer-kInitialDelay, ((kSmokeRadiusIncrease - fSpeed) * dt), 0.0f);

            smokeInstance.fCurrentRadius = clamp(fNewRadius, 0.0f, kMaxSmokeRadius);

            // If grenade on ground, then override its timer to be maximum of kMaxPhysicsSleepTime
            if((smokeInstance.state == eSIS_Active_PhysicsAsleep) && (smokeInstance.fTimer < kInitialDelay-kMaxPhysicsSleepTime))
                {
                    smokeInstance.fTimer = kInitialDelay-kMaxPhysicsSleepTime;
                }

            const float previousTimer = smokeInstance.fTimer;
            smokeInstance.fTimer = smokeInstance.fTimer + dt;

            if(previousTimer < kInitialDelay && smokeInstance.fTimer >= kInitialDelay)
                {
                    // Spawn explosion particle effect
                    if (m_pExplosionParticleEffect)
                        {
                            m_pExplosionParticleEffect->Spawn(false,IParticleEffect::ParticleLoc(vNewPosition));
                        }

                    // Spawn smoke particle effect
                    // Find a free slot on the grenade
                    SEntitySlotInfo dummySlotInfo;
                    int i=0;
                    while (pGrenade->GetSlotInfo(i, dummySlotInfo))
                        {
                            i++;
                        }
                    if (m_pOutsideSmokeParticleEffect)
                        {
                            pGrenade->LoadParticleEmitter(i, m_pOutsideSmokeParticleEffect);

                            IParticleEmitter* pEmitter = pGrenade->GetParticleEmitter(i);
                            if(pEmitter)
                                {
                                    SpawnParams spawnParams;
                                    pEmitter->GetSpawnParams(spawnParams);
                                    pEmitter->SetSpawnParams(spawnParams);
                                }
                        }
                }

            //Update the smoke's position
            smokeInstance.vPositon = vNewPosition;

            if (smokeInstance.pObstructObject)
                {
                    pe_params_pos pos;
                    pos.scale = clamp(smokeInstance.fCurrentRadius * __fres(kMaxSmokeRadius), 0.1f, 1.0f);
                    pos.pos = vNewPosition;
                    smokeInstance.pObstructObject->SetParams(&pos);
                }
        }
    else
        {
            //The grenade entity has been deleted, so smoke has stopped being produced
            if(smokeInstance.fTimer > kSmokeEmitEndTime)
                {
                    //The smoke has cleared, delete the SmokeInstance
                    smokeInstance.state = eSIS_ForDeletion;
                }
            else
                {
                    //Count down the remaining life, and reduce the radius
                    smokeInstance.fTimer					+= dt;
                    smokeInstance.fCurrentRadius  = max(smokeInstance.fCurrentRadius - (dt * kMaxSmokeRadius / kSmokeLingerTime), 0.0f);

                    if (smokeInstance.pObstructObject)
                        {
                            pe_params_pos pos;
                            pos.scale = clamp(smokeInstance.fCurrentRadius * __fres(kMaxSmokeRadius), 0.1f, 1.0f);

                            smokeInstance.pObstructObject->SetParams(&pos);
                        }
                }
        }
}
Beispiel #15
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;
}