|
|
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Implements the server side of a steam jet particle system entity.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "smokestack.h"
#include "particle_light.h"
#include "filesystem.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//Networking
IMPLEMENT_SERVERCLASS_ST(CSmokeStack, DT_SmokeStack) SendPropFloat(SENDINFO(m_SpreadSpeed), 0, SPROP_NOSCALE), SendPropFloat(SENDINFO(m_Speed), 0, SPROP_NOSCALE), SendPropFloat(SENDINFO(m_StartSize), 0, SPROP_NOSCALE), SendPropFloat(SENDINFO(m_EndSize), 0, SPROP_NOSCALE), SendPropFloat(SENDINFO(m_Rate), 0, SPROP_NOSCALE), SendPropFloat(SENDINFO(m_JetLength), 0, SPROP_NOSCALE), SendPropInt(SENDINFO(m_bEmit), 1, SPROP_UNSIGNED), SendPropFloat(SENDINFO(m_flBaseSpread), 0, SPROP_NOSCALE), SendPropFloat(SENDINFO( m_flRollSpeed ), 0, SPROP_NOSCALE ),
// Note: the base color is specified in the smokestack entity, but the directional
// and ambient light must come from env_particlelight entities.
SendPropVector( SENDINFO_NOCHECK(m_DirLight.m_vPos), 0, SPROP_NOSCALE ), SendPropVector( SENDINFO_NOCHECK(m_DirLight.m_vColor), 0, SPROP_NOSCALE ), SendPropFloat( SENDINFO_NOCHECK(m_DirLight.m_flIntensity), 0, SPROP_NOSCALE ),
SendPropVector( SENDINFO_NOCHECK(m_AmbientLight.m_vPos), 0, SPROP_NOSCALE ), SendPropVector( SENDINFO_NOCHECK(m_AmbientLight.m_vColor), 0, SPROP_NOSCALE ), SendPropFloat( SENDINFO_NOCHECK(m_AmbientLight.m_flIntensity), 0, SPROP_NOSCALE ),
SendPropVector(SENDINFO(m_vWind), 0, SPROP_NOSCALE), SendPropFloat(SENDINFO(m_flTwist), 0, SPROP_NOSCALE), SendPropIntWithMinusOneFlag( SENDINFO(m_iMaterialModel), 16 )
END_SEND_TABLE()
LINK_ENTITY_TO_CLASS( env_smokestack, CSmokeStack );
//Save/restore
BEGIN_SIMPLE_DATADESC( CSmokeStackLightInfo ) DEFINE_FIELD( m_vPos, FIELD_POSITION_VECTOR ), DEFINE_FIELD( m_vColor, FIELD_VECTOR ), DEFINE_FIELD( m_flIntensity, FIELD_FLOAT ), END_DATADESC()
BEGIN_DATADESC( CSmokeStack )
//Keyvalue fields
DEFINE_KEYFIELD( m_StartSize, FIELD_FLOAT, "StartSize" ), DEFINE_KEYFIELD( m_EndSize, FIELD_FLOAT, "EndSize" ), DEFINE_KEYFIELD( m_InitialState, FIELD_BOOLEAN, "InitialState" ), DEFINE_KEYFIELD( m_flBaseSpread, FIELD_FLOAT, "BaseSpread" ), DEFINE_KEYFIELD( m_flTwist, FIELD_FLOAT, "Twist" ), DEFINE_KEYFIELD( m_flRollSpeed, FIELD_FLOAT, "Roll" ),
DEFINE_FIELD( m_strMaterialModel, FIELD_STRING ), DEFINE_FIELD( m_iMaterialModel,FIELD_INTEGER ),
DEFINE_EMBEDDED( m_AmbientLight ), DEFINE_EMBEDDED( m_DirLight ),
DEFINE_KEYFIELD( m_WindAngle, FIELD_INTEGER, "WindAngle" ), DEFINE_KEYFIELD( m_WindSpeed, FIELD_INTEGER, "WindSpeed" ),
//Regular fields
DEFINE_FIELD( m_vWind, FIELD_VECTOR ), DEFINE_FIELD( m_bEmit, FIELD_INTEGER ),
// Inputs
DEFINE_INPUT( m_JetLength, FIELD_FLOAT, "JetLength" ), DEFINE_INPUT( m_SpreadSpeed, FIELD_FLOAT, "SpreadSpeed" ), DEFINE_INPUT( m_Speed, FIELD_FLOAT, "Speed" ), DEFINE_INPUT( m_Rate, FIELD_FLOAT, "Rate" ),
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
END_DATADESC()
//-----------------------------------------------------------------------------
// Purpose: Called before spawning, after key values have been set.
//-----------------------------------------------------------------------------
CSmokeStack::CSmokeStack() { memset( &m_AmbientLight, 0, sizeof(m_AmbientLight) ); memset( &m_DirLight, 0, sizeof(m_DirLight) );
IMPLEMENT_NETWORKVAR_CHAIN( &m_AmbientLight ); IMPLEMENT_NETWORKVAR_CHAIN( &m_DirLight );
m_flTwist = 0; SetRenderColor( 0, 0, 0 ); SetRenderAlpha( 255 ); m_vWind.GetForModify().Init(); m_WindAngle = m_WindSpeed = 0; m_iMaterialModel = -1; m_flRollSpeed = 0.0f; }
CSmokeStack::~CSmokeStack() { }
void CSmokeStack::Spawn( void ) { if ( m_InitialState ) { m_bEmit = true; } }
void CSmokeStack::Activate() { DetectInSkybox();
bool bGotDirLight = false;
// Find local lights.
CBaseEntity *pTestEnt = NULL; while ( 1 ) { pTestEnt = gEntList.FindEntityByClassname( pTestEnt, PARTICLELIGHT_ENTNAME ); if ( !pTestEnt ) break;
CParticleLight *pLight = (CParticleLight*)pTestEnt; if( !FStrEq( STRING(GetEntityName()), STRING(pLight->m_PSName) ) ) continue;
CSmokeStackLightInfo *pInfo = &m_AmbientLight; if ( pLight->m_bDirectional ) { bGotDirLight = true; pInfo = &m_DirLight; }
pInfo->m_flIntensity = pLight->m_flIntensity; pInfo->m_vColor = pLight->m_vColor; pInfo->m_vPos = pLight->GetAbsOrigin(); }
// Put our light colors in 0-1 space.
m_AmbientLight.m_vColor.GetForModify() /= 255.0f; m_DirLight.m_vColor.GetForModify() /= 255.0f;
BaseClass::Activate();
// Legacy support..
if ( m_iMaterialModel == -1 ) m_iMaterialModel = PrecacheModel( "particle/SmokeStack.vmt" ); }
bool CSmokeStack::KeyValue( const char *szKeyName, const char *szValue ) { if( stricmp( szKeyName, "Wind" ) == 0 ) { sscanf( szValue, "%f %f %f", &m_vWind.GetForModify().x, &m_vWind.GetForModify().y, &m_vWind.GetForModify().z ); return true; } else if( stricmp( szKeyName, "WindAngle" ) == 0 ) { m_WindAngle = atoi( szValue ); RecalcWindVector(); return true; } else if( stricmp( szKeyName, "WindSpeed" ) == 0 ) { m_WindSpeed = atoi( szValue ); RecalcWindVector(); return true; } else if ( stricmp( szKeyName, "SmokeMaterial" ) == 0 ) { // Make sure we have a vmt extension.
if ( Q_stristr( szValue, ".vmt" ) ) { m_strMaterialModel = AllocPooledString( szValue ); } else { char str[512]; Q_snprintf( str, sizeof( str ), "%s.vmt", szValue ); m_strMaterialModel = AllocPooledString( str ); } const char *pName = STRING( m_strMaterialModel ); char szStrippedName[512];
m_iMaterialModel = PrecacheModel( pName ); Q_StripExtension( pName, szStrippedName, Q_strlen(pName)+1 );
int iLength = Q_strlen( szStrippedName ); szStrippedName[iLength-1] = '\0';
int iCount = 1; char str[512]; Q_snprintf( str, sizeof( str ), "%s%d.vmt", szStrippedName, iCount ); while ( filesystem->FileExists( UTIL_VarArgs( "materials/%s", str ) ) ) { PrecacheModel( str ); iCount++; Q_snprintf( str, sizeof( str ), "%s%d.vmt", szStrippedName, iCount ); }
return true; } else { return BaseClass::KeyValue( szKeyName, szValue ); } }
void CSmokeStack::Precache() { m_iMaterialModel = PrecacheModel( STRING( m_strMaterialModel ) ); BaseClass::Precache(); }
//-----------------------------------------------------------------------------
// Purpose: Input handler for toggling the steam jet on/off.
//-----------------------------------------------------------------------------
void CSmokeStack::InputToggle( inputdata_t &inputdata ) { m_bEmit = !m_bEmit; }
//-----------------------------------------------------------------------------
// Purpose: Input handler for turning on the steam jet.
//-----------------------------------------------------------------------------
void CSmokeStack::InputTurnOn( inputdata_t &inputdata ) { m_bEmit = true; }
//-----------------------------------------------------------------------------
// Purpose: Input handler for turning off the steam jet.
//-----------------------------------------------------------------------------
void CSmokeStack::InputTurnOff( inputdata_t &inputdata ) { m_bEmit = false; }
void CSmokeStack::RecalcWindVector() { m_vWind = Vector( cos( DEG2RAD( (float)m_WindAngle ) ) * m_WindSpeed, sin( DEG2RAD( (float)m_WindAngle ) ) * m_WindSpeed, 0 ); }
|