Rain splashes: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
No edit summary
(Fixed issues with code)
Line 1: Line 1:
[[Category:Free source code]]
[[Category:Free source code]]
== Requirements ==
You must be using the Source 2007 or Source 2009 engine for this to work. You also need to have a pre-made splash particle system.
== Source Code ==
== Source Code ==


Line 8: Line 12:
ConVar r_RainSplashPercentage( "r_RainSplashPercentage", "99", FCVAR_CHEAT ); // N% chance of a rain particle making a splash.
ConVar r_RainSplashPercentage( "r_RainSplashPercentage", "99", FCVAR_CHEAT ); // N% chance of a rain particle making a splash.


'''NOTE: PLEASE REPLACE XXX'S WITH YOUR PARTICLE SYSTEM'''
Now, simply the function at line 295 with the following code:
 
''Code provided by [[Tony Sergi]]''
 
inline bool CClient_Precipitation::SimulateRain( CPrecipitationParticle* pParticle, float dt )
{
if (GetRemainingLifetime( pParticle ) < 0.0f)
return false;
Vector vOldPos = pParticle->m_Pos;
// Update position
VectorMA( pParticle->m_Pos, dt, pParticle->m_Velocity,
pParticle->m_Pos );
// wind blows rain around
for ( int i = 0 ; i < 2 ; i++ )
{
if ( pParticle->m_Velocity[i] < s_WindVector[i] )
{
pParticle->m_Velocity[i] += ( 5 / pParticle->m_Mass );
// clamp
if ( pParticle->m_Velocity[i] > s_WindVector[i] )
pParticle->m_Velocity[i] = s_WindVector[i];
}
else if (pParticle->m_Velocity[i] > s_WindVector[i] )
{
pParticle->m_Velocity[i] -= ( 5 / pParticle->m_Mass );
// clamp.
if ( pParticle->m_Velocity[i] < s_WindVector[i] )
pParticle->m_Velocity[i] = s_WindVector[i];
}
}
/*
// No longer in the air? punt.
if ( !IsInAir( pParticle->m_Pos ) )
{
// Possibly make a splash if we hit a water surface and it's in front of the view.
if ( m_Splashes.Count() < 20 )
{
if ( RandomInt( 0, 100 ) < r_RainSplashPercentage.GetInt() )
{
trace_t trace;
UTIL_TraceLine(vOldPos, pParticle->m_Pos, MASK_WATER, NULL, C COLLISION_GROUP_NONE, &trace);
if( trace.fraction < 1 )
{
m_Splashes.AddToTail( trace.endpos );
}
}
}
// Tell the framework it's time to remove the particle from the list
return false;
}*/
    /*Tony; the traceline replaces the IsInAir check.
    you also don't want the random's to be around the traceline either, or it will only check SOMETIMES. it  needs to check _all_ the time.
    you also probably want to do some radius checking of the particles position (ignoring z) for if it's in range of the local player to run this code or not
    otherwise you will have traces for every particle all over the place even if there's no way that the player can see it
    so when the player is out of that radius, you would only use if ( !IsInAir( pParticle->m_Pos ) { return  false; }
    probably also need to check to make sure that it doesn't splash on sky, too.
  */
    trace_t trace;
      UTIL_TraceLine(vOldPos, pParticle->m_Pos, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trace);
    if( trace.fraction < 1 || trace.DidHit() )
    {
        if ( RandomInt( 0, 100 ) <= r_RainSplashPercentage.GetInt() )
            DispatchParticleEffect( "SPLASH_PARTICLE_NAME", trace.endpos,trace.m_pEnt->GetAbsAngles() , NULL );
        // Tell the framework it's time to remove the particle from the list
        return false;
    }
// We still want this particle
return true;
}
 
'''NOTE: REPLACE SPLASH_PARTICLE_NAME WITH YOUR PARTICLE SYSTEM'''


Now, simply replace the "if" function at line 331 in c_effects.cpp, in the Temporary Entites section of the client code, with the following code.


      if ( m_Splashes.Count() < 99 )
      {
        if ( RandomInt( 0, 100 ) < r_RainSplashPercentage.GetInt() )
        {
            trace_t trace;
            UTIL_TraceLine(vOldPos, pParticle->m_Pos, MASK_ALL, NULL, COLLISION_GROUP_NPC, &trace);
            if( trace.fraction < 1 )
            {
              DispatchParticleEffect( "XXXX", trace.endpos, trace.m_pEnt->GetAbsAngles() , NULL );                     
            }
        }
      }
[[Image:Rain_standards0005.jpg|thumb|If you set up things correctly, you will see this!]]
[[Image:Rain_standards0005.jpg|thumb|If you set up things correctly, you will see this!]]


Line 30: Line 101:
[[Image:Rain_standards0000.jpg|thumb|What will happen if your particle is not precached.]]
[[Image:Rain_standards0000.jpg|thumb|What will happen if your particle is not precached.]]
The only specifications needed for your splash particle are that it be precached (See [[Particles_manifest.txt]]), and that it has "Constrain distance between control points" in the Constraints section of your particle.
The only specifications needed for your splash particle are that it be precached (See [[Particles_manifest.txt]]), and that it has "Constrain distance between control points" in the Constraints section of your particle.
== Issues ==
Currently this does not work on glass or displacement surfaces; looking for a way to fix this. Splashes will no longer appear on water.

Revision as of 17:39, 22 May 2010

Requirements

You must be using the Source 2007 or Source 2009 engine for this to work. You also need to have a pre-made splash particle system.

Source Code

By default the rain splashes done in c_effects.cpp in the Simulate Rain function take place 20% of the time, and more importantly, only on water. This snippet will allow the rain to work on almost all surfaces, including static props, and also allows for a custom rain splash particle effect.

First, replace line 36 in c_effects.cpp with the following code.

ConVar r_RainSplashPercentage( "r_RainSplashPercentage", "99", FCVAR_CHEAT ); // N% chance of a rain particle making a splash.

Now, simply the function at line 295 with the following code:

Code provided by Tony Sergi

inline bool CClient_Precipitation::SimulateRain( CPrecipitationParticle* pParticle, float dt )
{
	if (GetRemainingLifetime( pParticle ) < 0.0f)
		return false;

	Vector vOldPos = pParticle->m_Pos;

	// Update position
	VectorMA( pParticle->m_Pos, dt, pParticle->m_Velocity, 
				pParticle->m_Pos );

	// wind blows rain around
	for ( int i = 0 ; i < 2 ; i++ )
	{
		if ( pParticle->m_Velocity[i] < s_WindVector[i] )
		{
			pParticle->m_Velocity[i] += ( 5 / pParticle->m_Mass );

			// clamp
			if ( pParticle->m_Velocity[i] > s_WindVector[i] )
				pParticle->m_Velocity[i] = s_WindVector[i];
		}
		else if (pParticle->m_Velocity[i] > s_WindVector[i] )
		{
			pParticle->m_Velocity[i] -= ( 5 / pParticle->m_Mass );

			// clamp.
			if ( pParticle->m_Velocity[i] < s_WindVector[i] )
				pParticle->m_Velocity[i] = s_WindVector[i];
		}
	}

	/*
	// No longer in the air? punt.
	if ( !IsInAir( pParticle->m_Pos ) )
	{
		// Possibly make a splash if we hit a water surface and it's in front of the view.
		if ( m_Splashes.Count() < 20 )
		{
			if ( RandomInt( 0, 100 ) < r_RainSplashPercentage.GetInt() )
			{
				trace_t trace;
				UTIL_TraceLine(vOldPos, pParticle->m_Pos, MASK_WATER, NULL, C COLLISION_GROUP_NONE, &trace);
				if( trace.fraction < 1 )
				{
					m_Splashes.AddToTail( trace.endpos );
				}
			}
		}

		// Tell the framework it's time to remove the particle from the list
		return false;
	}*/
   /*Tony; the traceline replaces the IsInAir check.
   you also don't want the random's to be around the traceline either, or it will only check SOMETIMES. it  needs to check _all_ the time.
    you also probably want to do some radius checking of the particles position (ignoring z) for if it's in range of the local player to run this code or not
    otherwise you will have traces for every particle all over the place even if there's no way that the player can see it
   so when the player is out of that radius, you would only use if ( !IsInAir( pParticle->m_Pos ) { return  false; }
    probably also need to check to make sure that it doesn't splash on sky, too.
  */
    trace_t trace;
     UTIL_TraceLine(vOldPos, pParticle->m_Pos, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trace);

    if( trace.fraction < 1 || trace.DidHit() )
   {
        if ( RandomInt( 0, 100 ) <= r_RainSplashPercentage.GetInt() )
           DispatchParticleEffect( "SPLASH_PARTICLE_NAME", trace.endpos,trace.m_pEnt->GetAbsAngles() , NULL );

       // Tell the framework it's time to remove the particle from the list
       return false;
   }

	// We still want this particle
	return true;
}

NOTE: REPLACE SPLASH_PARTICLE_NAME WITH YOUR PARTICLE SYSTEM


If you set up things correctly, you will see this!

Particle Setup

What will happen if your particle is not precached.

The only specifications needed for your splash particle are that it be precached (See Particles_manifest.txt), and that it has "Constrain distance between control points" in the Constraints section of your particle.