- Sep 23, 2011
- 2,075
- 515
I am sure that most of us have at least noticed the existence of a dev/dev_slime material when skimming the dev folder in the texture browser. But what does it do?
Let's start by looking at the material itself:
Ok, so it passes the %compileSlime flag to vbsp. What does that mean?
Now it's passed along as CONTENTS_SLIME. Lets see where the game code checks for that!
First up we have some old quake code. I can only assume that Valve didn't keep this one when they redesigned their physics system.
Next up we have some mentions in the HL2 source code:
There is also a mention in physics_fx.cpp, again for making splashes.
Both of these use the FX_WATER_IN_SLIME constant. Lets see where that is used:
Looks like we are getting close to a meaningful difference in behaviour!
So, this ultimately ends up as water that has a different particle effect when shot at. Clearly an important difference from water.
If anyone know of any more differences, please just post them in this topic.
Let's start by looking at the material itself:
Code:
// dev/dev_slime.vmt
"LightmappedGeneric"
{
// Original shader: BaseTimesLightmap
"%compileSlime" 1
"$basetexture" "Dev/dev_slime"
"$surfaceprop" "slime"
}
Ok, so it passes the %compileSlime flag to vbsp. What does that mean?
Code:
// from int FindMiptex (const char *name) in textures.cpp
// https://github.com/Noiwex/hl2sb-src/blob/master/src/utils/vbsp/textures.cpp#L261
if ( ( propVal = GetMaterialVar( matID, "%compileSlime" ) ) &&
StringIsTrue( propVal ) )
{
textureref[i].contents &= ~(CONTENTS_SOLID|CONTENTS_DETAIL);
textureref[i].contents |= CONTENTS_SLIME;
textureref[i].flags |= SURF_NODECALS;
// Set this so that we can check at the end of the process the presence of a a WaterLODControl entity.
g_bHasWater = true;
}
Now it's passed along as CONTENTS_SLIME. Lets see where the game code checks for that!
First up we have some old quake code. I can only assume that Valve didn't keep this one when they redesigned their physics system.
Code:
//void JumpButton (void)
//http://osxr.org:8080/android/source/external/quake/quake/src/QW/client/pmove.c#0667
if (waterlevel >= 2)
{ // swimming, not jumping
onground = -1;
if (watertype == CONTENTS_WATER)
pmove.velocity[2] = 100;
else if (watertype == CONTENTS_SLIME)
pmove.velocity[2] = 80;
else
pmove.velocity[2] = 50;
return;
}
Next up we have some mentions in the HL2 source code:
Code:
// https://github.com/ValveSoftware/source-sdk-2013/blob/master/sp/src/game/server/basebludgeonweapon.cpp#L236
bool CBaseHLBludgeonWeapon::ImpactWater( const Vector &start, const Vector &end )
{
//FIXME: This doesn't handle the case of trying to splash while being underwater, but that's not going to look good
// right now anyway...
// We must start outside the water
if ( UTIL_PointContents( start ) & (CONTENTS_WATER|CONTENTS_SLIME))
return false;
// We must end inside of water
if ( !(UTIL_PointContents( end ) & (CONTENTS_WATER|CONTENTS_SLIME)))
return false;
trace_t waterTrace;
UTIL_TraceLine( start, end, (CONTENTS_WATER|CONTENTS_SLIME), GetOwner(), COLLISION_GROUP_NONE, &waterTrace );
if ( waterTrace.fraction < 1.0f )
{
CEffectData data;
data.m_fFlags = 0;
data.m_vOrigin = waterTrace.endpos;
data.m_vNormal = waterTrace.plane.normal;
data.m_flScale = 8.0f;
// See if we hit slime
if ( waterTrace.contents & CONTENTS_SLIME )
{
data.m_fFlags |= FX_WATER_IN_SLIME;
}
DispatchEffect( "watersplash", data );
}
return true;
}
There is also a mention in physics_fx.cpp, again for making splashes.
Both of these use the FX_WATER_IN_SLIME constant. Lets see where that is used:
Code:
// http://hlssmod.net/he_code/game/client/fx_water.cpp
void SplashCallback( const CEffectData &data )
{
Vector normal;
AngleVectors( data.m_vAngles, &normal );
if ( data.m_fFlags & FX_WATER_IN_SLIME )
{
FX_GunshotSlimeSplash( data.m_vOrigin, Vector(0,0,1), data.m_flScale );
}
else
{
FX_GunshotSplash( data.m_vOrigin, Vector(0,0,1), data.m_flScale );
}
}
DECLARE_CLIENT_EFFECT( "watersplash", SplashCallback );
void GunshotSplashCallback( const CEffectData &data )
{
if ( data.m_fFlags & FX_WATER_IN_SLIME )
{
FX_GunshotSlimeSplash( data.m_vOrigin, Vector(0,0,1), data.m_flScale );
}
else
{
FX_GunshotSplash( data.m_vOrigin, Vector(0,0,1), data.m_flScale );
}
}
DECLARE_CLIENT_EFFECT( "gunshotsplash", GunshotSplashCallback );
Looks like we are getting close to a meaningful difference in behaviour!
Code:
void FX_GunshotSlimeSplash( const Vector &origin, const Vector &normal, float scale )
{
if ( cl_show_splashes.GetBool() == false )
return;
VPROF_BUDGET( "FX_GunshotSlimeSplash", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
#if 0
// cut for brevity since it's not used
// it's more or less identical to the code of FX_GunshotSplash, but with a different effect material
#else
QAngle vecAngles;
VectorAngles( normal, vecAngles );
if ( scale < 2.0f )
{
DispatchParticleEffect( "slime_splash_01", origin, vecAngles );
}
else if ( scale < 4.0f )
{
DispatchParticleEffect( "slime_splash_02", origin, vecAngles );
}
else
{
DispatchParticleEffect( "slime_splash_03", origin, vecAngles );
}
#endif
//Play a sound
CLocalPlayerFilter filter;
EmitSound_t ep;
ep.m_nChannel = CHAN_VOICE;
ep.m_pSoundName = "Physics.WaterSplash";
ep.m_flVolume = 1.0f;
ep.m_SoundLevel = SNDLVL_NORM;
ep.m_pOrigin = &origin;
C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, ep );
}
So, this ultimately ends up as water that has a different particle effect when shot at. Clearly an important difference from water.
If anyone know of any more differences, please just post them in this topic.