//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
//=============================================================================//

#include "cbase.h"
#include "weapon_mg42.h"
#include "engine/ivdebugoverlay.h"

#if defined( CLIENT_DLL )

	#include "tier1/KeyValues.h"
	#include "particles_simple.h"
	#include "particles_localspace.h"
	#include "fx.h"
	#include "c_dod_player.h"

#else
	
	#include "dod_player.h"

#endif


#ifdef CLIENT_DLL	
void ToolFramework_PostToolMessage( HTOOLHANDLE hEntity, KeyValues *msg );
#endif


IMPLEMENT_NETWORKCLASS_ALIASED( WeaponMG42, DT_WeaponMG42 )

#ifdef GAME_DLL

BEGIN_DATADESC( CWeaponMG42 )
	DEFINE_THINKFUNC( CoolThink ),
END_DATADESC()

#endif

BEGIN_NETWORK_TABLE( CWeaponMG42, DT_WeaponMG42 )
#ifdef CLIENT_DLL	
	RecvPropInt			( RECVINFO( m_iWeaponHeat ) ),
	RecvPropTime		( RECVINFO( m_flNextCoolTime ) ),
	RecvPropBool		( RECVINFO( m_bOverheated ) ),
#else
	SendPropInt			( SENDINFO( m_iWeaponHeat ), 7, SPROP_UNSIGNED ),
	SendPropFloat		( SENDINFO( m_flNextCoolTime ) ),
	SendPropBool		( SENDINFO( m_bOverheated ) ),
#endif
END_NETWORK_TABLE()

#ifdef CLIENT_DLL
BEGIN_PREDICTION_DATA( CWeaponMG42 )
	DEFINE_PRED_FIELD( m_iWeaponHeat, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
	DEFINE_PRED_FIELD_TOL( m_flNextCoolTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, TD_MSECTOLERANCE ),
	DEFINE_PRED_FIELD( m_bOverheated, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
END_PREDICTION_DATA()
#endif

LINK_ENTITY_TO_CLASS( weapon_mg42, CWeaponMG42 );
PRECACHE_WEAPON_REGISTER( weapon_mg42 );

acttable_t CWeaponMG42::m_acttable[] = 
{
	{ ACT_DOD_STAND_AIM,					ACT_DOD_STAND_AIM_MG,				false },
	{ ACT_DOD_CROUCH_AIM,					ACT_DOD_CROUCH_AIM_MG,				false },
	{ ACT_DOD_CROUCHWALK_AIM,				ACT_DOD_CROUCHWALK_AIM_MG,			false },
	{ ACT_DOD_WALK_AIM,						ACT_DOD_WALK_AIM_MG,				false },
	{ ACT_DOD_RUN_AIM,						ACT_DOD_RUN_AIM_MG,					false },
	{ ACT_PRONE_IDLE,						ACT_DOD_PRONE_AIM_MG,				false },
	{ ACT_PRONE_FORWARD,					ACT_DOD_PRONEWALK_IDLE_MG,			false },
	{ ACT_DOD_STAND_IDLE,					ACT_DOD_STAND_IDLE_MG,				false },
	{ ACT_DOD_CROUCH_IDLE,					ACT_DOD_CROUCH_IDLE_MG,				false },
	{ ACT_DOD_CROUCHWALK_IDLE,				ACT_DOD_CROUCHWALK_IDLE_MG,			false },
	{ ACT_DOD_WALK_IDLE,					ACT_DOD_WALK_IDLE_MG,				false },
	{ ACT_DOD_RUN_IDLE,						ACT_DOD_RUN_IDLE_MG,				false },
	{ ACT_SPRINT,							ACT_DOD_SPRINT_IDLE_MG,				false },

	// Deployed Aim
	{ ACT_DOD_DEPLOYED,						ACT_DOD_DEPLOY_MG,						false },
	{ ACT_DOD_PRONE_DEPLOYED,				ACT_DOD_PRONE_DEPLOY_MG,				false },

	// Attack ( prone? deployed? )
	{ ACT_RANGE_ATTACK1,					ACT_DOD_PRIMARYATTACK_MG,				false },
	{ ACT_DOD_PRIMARYATTACK_CROUCH,			ACT_DOD_PRIMARYATTACK_MG,				false },
	{ ACT_DOD_PRIMARYATTACK_PRONE,			ACT_DOD_PRIMARYATTACK_PRONE_MG,			false },
	{ ACT_DOD_PRIMARYATTACK_DEPLOYED,		ACT_DOD_PRIMARYATTACK_DEPLOYED_MG,		false },
	{ ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED,	ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED_MG,false },

	// Reload ( prone? deployed? )	
	{ ACT_DOD_RELOAD_DEPLOYED,				ACT_DOD_RELOAD_DEPLOYED_MG,				false },
	{ ACT_DOD_RELOAD_PRONE_DEPLOYED,		ACT_DOD_RELOAD_PRONE_DEPLOYED_MG,		false },

	// Hand Signals
	{ ACT_DOD_HS_IDLE,						ACT_DOD_HS_IDLE_MG42,					false },
	{ ACT_DOD_HS_CROUCH,					ACT_DOD_HS_CROUCH_MG42,					false },
};

IMPLEMENT_ACTTABLE( CWeaponMG42 );

void CWeaponMG42::Spawn( void )
{
	m_iWeaponHeat = 0;
	m_flNextCoolTime = 0;

	m_bOverheated = false;

#ifdef CLIENT_DLL
	m_pEmitter = NULL;
	m_flParticleAccumulator = 0.0;
	m_hParticleMaterial = ParticleMgr()->GetPMaterial( "sprites/effects/bazookapuff" );
#endif	

	BaseClass::Spawn();
}

#ifdef CLIENT_DLL

	CWeaponMG42::~CWeaponMG42()
	{
		if ( clienttools->IsInRecordingMode() && m_pEmitter.IsValid() && m_pEmitter->GetToolParticleEffectId() != TOOLPARTICLESYSTEMID_INVALID )
		{
			KeyValues *msg = new KeyValues( "ParticleSystem_ActivateEmitter" );
			msg->SetInt( "id", m_pEmitter->GetToolParticleEffectId() );
			msg->SetFloat( "time", gpGlobals->curtime );
			msg->SetInt( "active", 0 );

			msg->SetInt( "emitter", 0 );
			ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );

			msg->SetInt( "emitter", 1 );
			ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );

			msg->SetInt( "emitter", 2 );
			ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );

			msg->SetInt( "emitter", 3 );
			ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );

			msg->deleteThis();
		}
	}

	void CWeaponMG42::OnDataChanged( DataUpdateType_t updateType )
	{
		BaseClass::OnDataChanged( updateType );

		// BUG! This can happen more than once!
		if ( updateType == DATA_UPDATE_CREATED )
		{
			if ( !m_pEmitter.IsValid() )
			{
				m_pEmitter = CSimpleEmitter::Create( "MGOverheat" );
			}

			Assert( m_pEmitter.IsValid() );
		}

		ClientThinkList()->SetNextClientThink( GetClientHandle(), CLIENT_THINK_ALWAYS );
	}

	// Client Think emits smoke particles based on heat
	// ( except if we are holstered )
	void CWeaponMG42::ClientThink( void )
	{
		m_pEmitter->SetSortOrigin( GetAbsOrigin() );

		float flEmitRate = 0.0;	//particles per second

		// Only smoke if we are dropped ( no owner ) or if we have an owner and are active
		if ( GetOwner() == NULL || GetOwner()->GetActiveWeapon() == this )
		{
			if ( m_iWeaponHeat > 85 )
			{	
				flEmitRate = 30;
			}
			else if ( m_iWeaponHeat > 80 )
			{
				flEmitRate = 20;
			}
			else if ( m_iWeaponHeat > 65 )
			{
				flEmitRate = 10;
			}
			else if ( m_iWeaponHeat > 50 )
			{
				flEmitRate = 5;
			}
		}

		m_flParticleAccumulator += ( gpGlobals->frametime * flEmitRate );

		while( m_flParticleAccumulator > 0.0 )
		{
			EmitSmokeParticle();

			m_flParticleAccumulator -= 1.0;
		}
	}

	void CWeaponMG42::EmitSmokeParticle( void )
	{
		Vector vFront, vBack;	
		QAngle angles;

		C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();

		bool bViewModel = false;

		// if this is locally owned
		if ( GetPlayerOwner() == pLocalPlayer )
		{
			C_BaseViewModel *vm = pLocalPlayer->GetViewModel( 0 );

			if ( !vm )
				return;

			vm->GetAttachment( 1, vFront, angles );
			vm->GetAttachment( 2, vBack, angles );

			bViewModel = true;
		}
		else
		{
			// could be dropped, or held by another player
			GetAttachment( 1, vFront, angles );
			GetAttachment( 2, vBack, angles );
		}

		// Get a position somewhere on the barrel
		Vector vPos = vBack + random->RandomFloat(0.0, 1.0 ) * ( vFront - vBack );

		SimpleParticle *pParticle = m_pEmitter->AddSimpleParticle( m_hParticleMaterial, vPos );
		if ( pParticle )
		{
			pParticle->m_vecVelocity = Vector( 0,0,12 );
			pParticle->m_flRoll = random->RandomFloat( 0, 0.5 );
			pParticle->m_flRollDelta = ( random->RandomInt(0,1) == 0 ? 1 : -1 ) * random->RandomFloat( 0.5, 1.0 );
			pParticle->m_flDieTime = 1.8f;
			pParticle->m_flLifetime = 0;
			pParticle->m_uchColor[0] = 200;
			pParticle->m_uchColor[1] = 200; 
			pParticle->m_uchColor[2] = 200;
			pParticle->m_uchStartAlpha = 60;
			pParticle->m_uchEndAlpha = 0;
			pParticle->m_uchStartSize = 4;
			pParticle->m_uchEndSize = 25;
			pParticle->m_iFlags = 0;	//bViewModel ? FLE_VIEWMODEL : 0;
		}
	}

#else

	// This function does the cooling when the weapon is dropped or holstered
	// regular, predicted cooling is done in ItemPostFrame
	void CWeaponMG42::CoolThink( void )
	{
		if ( m_iWeaponHeat > 0 )
			m_iWeaponHeat--;
		
		SetContextThink( &CWeaponMG42::CoolThink, gpGlobals->curtime + 0.1, COOL_CONTEXT );
	}

#endif	

void CWeaponMG42::Precache()
{
	PrecacheMaterial( "sprites/effects/bazookapuff" );

	PrecacheScriptSound( "Weapon_Mg42.OverHeat" );

	BaseClass::Precache();
}

bool CWeaponMG42::Reload( void )
{
	if( !IsDeployed() )
	{
#ifdef CLIENT_DLL
		CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );

		if ( pPlayer )
			pPlayer->HintMessage( HINT_MG_DEPLOY_TO_RELOAD );
#endif
		return false;
	}

	return BaseClass::Reload();
}

void CWeaponMG42::FinishReload( void )
{
	BaseClass::FinishReload();

	//Reset the heat when you complete a reload
	m_iWeaponHeat = 0;
}

void CWeaponMG42::PrimaryAttack( void )
{
	if( m_bOverheated )
	{
		return;
	}

	if ( m_iClip1 <= 0 )
	{
		if (m_bFireOnEmpty)
		{
			PlayEmptySound();
			m_flNextPrimaryAttack = gpGlobals->curtime + 0.2;
		}

		return;
	}


	CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
	Assert( pPlayer );

	if( m_iWeaponHeat >= 99 )
	{
		//can't fire anymore, wait until heat is below 80
#ifdef CLIENT_DLL 
		pPlayer->HintMessage( HINT_WEAPON_OVERHEAT );
#endif
		m_bOverheated = true;
		m_bInAttack = true;

		EmitSound( "Weapon_Mg42.OverHeat" );
		return;
	}

	m_iWeaponHeat += 1; //2;
	m_flNextCoolTime = gpGlobals->curtime + 0.16f;
	
	if( !IsDeployed() )
	{
#ifdef CLIENT_DLL 
		pPlayer->HintMessage( HINT_MG_FIRE_UNDEPLOYED );
#endif
		pPlayer->m_Shared.SetSlowedTime( 0.2 );

		float flStamina = pPlayer->m_Shared.GetStamina();

		pPlayer->m_Shared.SetStamina( flStamina - 15 );
	}

	BaseClass::PrimaryAttack();
}

void CWeaponMG42::ItemPostFrame( void )
{
	ItemFrameCool();

	if( m_iWeaponHeat < 80 )
		m_bOverheated = false;	

	BaseClass::ItemPostFrame();
}

void CWeaponMG42::ItemBusyFrame( void )
{
	ItemFrameCool();

	BaseClass::ItemBusyFrame();
}

void CWeaponMG42::ItemFrameCool( void )
{
	if( gpGlobals->curtime > m_flNextCoolTime )
	{
		if ( m_iWeaponHeat > 0 )
			m_iWeaponHeat--;

		m_flNextCoolTime = gpGlobals->curtime + 0.16f;
	}
}

bool CWeaponMG42::Deploy( void )
{
	// stop the fake cooling when we deploy the weapon
	SetContextThink( NULL, 0.0, COOL_CONTEXT );

	return BaseClass::Deploy();
}

bool CWeaponMG42::Holster( CBaseCombatWeapon *pSwitchingTo )
{
#ifndef CLIENT_DLL
	SetContextThink( &CWeaponMG42::CoolThink, gpGlobals->curtime + 0.1, COOL_CONTEXT );
#endif

	return BaseClass::Holster(pSwitchingTo);
}

void CWeaponMG42::Drop( const Vector &vecVelocity )
{
#ifndef CLIENT_DLL
	SetContextThink( &CWeaponMG42::CoolThink, gpGlobals->curtime + 0.1, COOL_CONTEXT );
#endif

	BaseClass::Drop( vecVelocity );
}

Activity CWeaponMG42::GetReloadActivity( void )
{
	return ACT_VM_RELOAD;
}

Activity CWeaponMG42::GetDrawActivity( void )
{
	Activity actDraw;

	if( 0 && m_iClip1 <= 0 )
		actDraw = ACT_VM_DRAW_EMPTY;	
	else
		actDraw = ACT_VM_DRAW;

	return actDraw;
}

Activity CWeaponMG42::GetDeployActivity( void )
{
	Activity actDeploy;

	switch ( m_iClip1 )
	{
	case 8:
		actDeploy = ACT_VM_DEPLOY_8;
		break;
	case 7:
		actDeploy = ACT_VM_DEPLOY_7;
		break;
	case 6:
		actDeploy = ACT_VM_DEPLOY_6;
		break;
	case 5:
		actDeploy = ACT_VM_DEPLOY_5;
		break;
	case 4:
		actDeploy = ACT_VM_DEPLOY_4;
		break;
	case 3:
		actDeploy = ACT_VM_DEPLOY_3;
		break;
	case 2:
		actDeploy = ACT_VM_DEPLOY_2;
		break;
	case 1:
		actDeploy = ACT_VM_DEPLOY_1;
		break;
	case 0:
		actDeploy = ACT_VM_DEPLOY_EMPTY;
		break;
	default:
		actDeploy = ACT_VM_DEPLOY;
		break;
	}

	return actDeploy;
}

Activity CWeaponMG42::GetUndeployActivity( void )
{
	Activity actUndeploy;

	switch ( m_iClip1 )
	{
	case 8:
		actUndeploy = ACT_VM_UNDEPLOY_8;
		break;
	case 7:
		actUndeploy = ACT_VM_UNDEPLOY_7;
		break;
	case 6:
		actUndeploy = ACT_VM_UNDEPLOY_6;
		break;
	case 5:
		actUndeploy = ACT_VM_UNDEPLOY_5;
		break;
	case 4:
		actUndeploy = ACT_VM_UNDEPLOY_4;
		break;
	case 3:
		actUndeploy = ACT_VM_UNDEPLOY_3;
		break;
	case 2:
		actUndeploy = ACT_VM_UNDEPLOY_2;
		break;
	case 1:
		actUndeploy = ACT_VM_UNDEPLOY_1;
		break;
	case 0:
		actUndeploy = ACT_VM_UNDEPLOY_EMPTY;
		break;
	default:
		actUndeploy = ACT_VM_UNDEPLOY;
		break;
	}

	return actUndeploy;
}

Activity CWeaponMG42::GetIdleActivity( void )
{
	Activity actIdle;

	if( IsDeployed() )
	{
		switch ( m_iClip1 )
		{
		case 8:
			actIdle = ACT_VM_IDLE_DEPLOYED_8;
			break;
		case 7:
			actIdle = ACT_VM_IDLE_DEPLOYED_7;
			break;
		case 6:
			actIdle = ACT_VM_IDLE_DEPLOYED_6;
			break;
		case 5:
			actIdle = ACT_VM_IDLE_DEPLOYED_5;
			break;
		case 4:
			actIdle = ACT_VM_IDLE_DEPLOYED_4;
			break;
		case 3:
			actIdle = ACT_VM_IDLE_DEPLOYED_3;
			break;
		case 2:
			actIdle = ACT_VM_IDLE_DEPLOYED_2;
			break;
		case 1:
			actIdle = ACT_VM_IDLE_DEPLOYED_1;
			break;
		case 0:
			actIdle = ACT_VM_IDLE_DEPLOYED_EMPTY;
			break;
		default:
			actIdle = ACT_VM_IDLE_DEPLOYED;
			break;
		}
	}
	else
	{
		switch ( m_iClip1 )
		{
		case 8:
			actIdle = ACT_VM_IDLE_8;
			break;
		case 7:
			actIdle = ACT_VM_IDLE_7;
			break;
		case 6:
			actIdle = ACT_VM_IDLE_6;
			break;
		case 5:
			actIdle = ACT_VM_IDLE_5;
			break;
		case 4:
			actIdle = ACT_VM_IDLE_4;
			break;
		case 3:
			actIdle = ACT_VM_IDLE_3;
			break;
		case 2:
			actIdle = ACT_VM_IDLE_2;
			break;
		case 1:
			actIdle = ACT_VM_IDLE_1;
			break;
		case 0:
			actIdle = ACT_VM_IDLE_EMPTY;
			break;
		default:
			actIdle = ACT_VM_IDLE;
			break;
		}
	}

	return actIdle;
}

Activity CWeaponMG42::GetPrimaryAttackActivity( void )
{
	Activity actPrim;

	if( IsDeployed() )
	{
		switch ( m_iClip1 )
		{
		case 8:
			actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_8;
			break;
		case 7:
			actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_7;
			break;
		case 6:
			actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_6;
			break;
		case 5:
			actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_5;
			break;
		case 4:
			actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_4;
			break;
		case 3:
			actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_3;
			break;
		case 2:
			actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_2;
			break;
		case 1:
			actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_1;
			break;
		case 0:
			actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_EMPTY;
			break;
		default:
			actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED;
			break;
		}
	}
	else
	{
		switch ( m_iClip1 )
		{
		case 8:
			actPrim = ACT_VM_PRIMARYATTACK_8;
			break;
		case 7:
			actPrim = ACT_VM_PRIMARYATTACK_7;
			break;
		case 6:
			actPrim = ACT_VM_PRIMARYATTACK_6;
			break;
		case 5:
			actPrim = ACT_VM_PRIMARYATTACK_5;
			break;
		case 4:
			actPrim = ACT_VM_PRIMARYATTACK_4;
			break;
		case 3:
			actPrim = ACT_VM_PRIMARYATTACK_3;
			break;
		case 2:
			actPrim = ACT_VM_PRIMARYATTACK_2;
			break;
		case 1:
			actPrim = ACT_VM_PRIMARYATTACK_1;
			break;
		case 0:
			actPrim = ACT_VM_PRIMARYATTACK_EMPTY;
			break;
		default:
			actPrim = ACT_VM_PRIMARYATTACK;
			break;
		}
	}

	return actPrim;
}

float CWeaponMG42::GetRecoil( void )
{
	CDODPlayer *p = ToDODPlayer( GetPlayerOwner() );

	if( p && p->m_Shared.IsInMGDeploy() )
	{
		return 0.0f;
	}

	return 20;
}

#ifdef CLIENT_DLL

//-----------------------------------------------------------------------------
// This is called after sending this entity's recording state
//-----------------------------------------------------------------------------
void CWeaponMG42::CleanupToolRecordingState( KeyValues *msg )
{
	BaseClass::CleanupToolRecordingState( msg );

	// Generally, this is used to allow the entity to clean up
	// allocated state it put into the message, but here we're going
	// to use it to send particle system messages because we
	// know the smoke has been recorded at this point
	if ( !clienttools->IsInRecordingMode() || !m_pEmitter.IsValid() )
		return;

	// NOTE: Particle system destruction message will be sent by the particle effect itself.
	if ( m_pEmitter->GetToolParticleEffectId() == TOOLPARTICLESYSTEMID_INVALID )
	{
		int nId = m_pEmitter->AllocateToolParticleEffectId();

		KeyValues *msg = new KeyValues( "ParticleSystem_Create" );
		msg->SetString( "name", "CWeaponMG42 smoke" );
		msg->SetInt( "id", nId );
		msg->SetFloat( "time", gpGlobals->curtime );

		KeyValues *pEmitter0 = msg->FindKey( "DmeSpriteEmitter", true );
		pEmitter0->SetInt( "count", 5 );	// particles per second, when duration is < 0
		pEmitter0->SetFloat( "duration", -1 );
		pEmitter0->SetString( "material", "sprites/effects/bazookapuff" );
		pEmitter0->SetInt( "active", 0 );

		KeyValues *pInitializers = pEmitter0->FindKey( "initializers", true );

		KeyValues *pPosition = pInitializers->FindKey( "DmeRandomAttachmentPositionEntityInitializer", true );
		pPosition->SetPtr( "entindex", (void*)entindex() );
 		pPosition->SetInt( "attachmentIndex0", 1 );
 		pPosition->SetInt( "attachmentIndex1", 2 );

		KeyValues *pLifetime = pInitializers->FindKey( "DmeRandomLifetimeInitializer", true );
		pLifetime->SetFloat( "minLifetime", 1.8f );
 		pLifetime->SetFloat( "maxLifetime", 1.8f );

		KeyValues *pVelocity = pInitializers->FindKey( "DmeConstantVelocityInitializer", true );
		pVelocity->SetFloat( "velocityX", 0.0f );
		pVelocity->SetFloat( "velocityY", 0.0f );
		pVelocity->SetFloat( "velocityZ", 12.0f );

		KeyValues *pRoll = pInitializers->FindKey( "DmeRandomRollInitializer", true );
		pRoll->SetFloat( "minRoll", 0.0f );
 		pRoll->SetFloat( "maxRoll", 0.5f );

		KeyValues *pRollSpeed = pInitializers->FindKey( "DmeSplitRandomRollSpeedInitializer", true );
		pRollSpeed->SetFloat( "minRollSpeed", 0.5f );
 		pRollSpeed->SetFloat( "maxRollSpeed", 1.0f );

		KeyValues *pColor = pInitializers->FindKey( "DmeRandomInterpolatedColorInitializer", true );
 		pColor->SetColor( "color1", Color( 200, 200, 200, 255 ) );
 		pColor->SetColor( "color2", Color( 200, 200, 200, 255 ) );

		KeyValues *pAlpha = pInitializers->FindKey( "DmeRandomAlphaInitializer", true );
		pAlpha->SetInt( "minStartAlpha", 60 );
		pAlpha->SetInt( "maxStartAlpha", 60 );
		pAlpha->SetInt( "minEndAlpha", 0 );
		pAlpha->SetInt( "maxEndAlpha", 0 );

		KeyValues *pSize = pInitializers->FindKey( "DmeRandomSizeInitializer", true );
		pSize->SetFloat( "minStartSize", 4 );
		pSize->SetFloat( "maxStartSize", 4 );
		pSize->SetFloat( "minEndSize", 25 );
		pSize->SetFloat( "maxEndSize", 25 );

		KeyValues *pUpdaters = pEmitter0->FindKey( "updaters", true );

		pUpdaters->FindKey( "DmePositionVelocityUpdater", true );
		pUpdaters->FindKey( "DmeRollUpdater", true );
		pUpdaters->FindKey( "DmeAlphaLinearUpdater", true );
		pUpdaters->FindKey( "DmeSizeUpdater", true );

		// create emitters for each emission rate: 5,10,20,30
		KeyValues *pEmitter1 = pEmitter0->MakeCopy();
		pEmitter1->SetInt( "count", 10 );
		msg->AddSubKey( pEmitter1 );

		KeyValues *pEmitter2 = pEmitter0->MakeCopy();
		pEmitter2->SetInt( "count", 20 );
		msg->AddSubKey( pEmitter2 );

		KeyValues *pEmitter3 = pEmitter0->MakeCopy();
		pEmitter3->SetInt( "count", 30 );
		msg->AddSubKey( pEmitter3 );

		// mark only the appropriate emitter active
		bool bHolstered = GetOwner() && GetOwner()->GetActiveWeapon() != this;
		if ( !bHolstered )
		{
			if ( m_iWeaponHeat > 85 )
			{
				pEmitter3->SetInt( "active", 1 );
			}
			else if ( m_iWeaponHeat > 80 )
			{
				pEmitter2->SetInt( "active", 1 );
			}
			else if ( m_iWeaponHeat > 65 )
			{
				pEmitter1->SetInt( "active", 1 );
			}
			else if ( m_iWeaponHeat > 50 )
			{
				pEmitter0->SetInt( "active", 1 );
			}
		}

		ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
		msg->deleteThis();
	}
	else
	{
		int nEmitterIndex = -1;
		bool bHolstered = GetOwner() && GetOwner()->GetActiveWeapon() != this;
		if ( !bHolstered )
		{
			if ( m_iWeaponHeat > 85 )
			{
				nEmitterIndex = 3;
			}
			else if ( m_iWeaponHeat > 80 )
			{
				nEmitterIndex = 2;
			}
			else if ( m_iWeaponHeat > 65 )
			{
				nEmitterIndex = 1;
			}
			else if ( m_iWeaponHeat > 50 )
			{
				nEmitterIndex = 0;
			}
		}

		KeyValues *msg = new KeyValues( "ParticleSystem_ActivateEmitter" );
		msg->SetInt( "id", m_pEmitter->GetToolParticleEffectId() );
		msg->SetFloat( "time", gpGlobals->curtime );

		msg->SetInt( "emitter", 0 );
		msg->SetInt( "active", nEmitterIndex == 0 );
		ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );

		msg->SetInt( "emitter", 1 );
		msg->SetInt( "active", nEmitterIndex == 1 );
		ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );

		msg->SetInt( "emitter", 2 );
		msg->SetInt( "active", nEmitterIndex == 2 );
		ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );

		msg->SetInt( "emitter", 3 );
		msg->SetInt( "active", nEmitterIndex == 3 );
		ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );

		msg->deleteThis();
	}
}

#endif