//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
// $Workfile:     $
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "c_te_particlesystem.h"
#include "tier1/KeyValues.h"
#include "toolframework_client.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"


//-----------------------------------------------------------------------------
// Purpose: Blood Stream TE
//-----------------------------------------------------------------------------
class C_TEBloodStream : public C_TEParticleSystem
{
public:
	DECLARE_CLASS( C_TEBloodStream, C_TEParticleSystem );
	DECLARE_CLIENTCLASS();

					C_TEBloodStream( void );
	virtual			~C_TEBloodStream( void );

	virtual void	PostDataUpdate( DataUpdateType_t updateType );

public:
	Vector			m_vecDirection;
	int				r, g, b, a;
	int				m_nAmount;
};


//-----------------------------------------------------------------------------
// Networking
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_EVENT_DT(C_TEBloodStream, DT_TEBloodStream, CTEBloodStream)
	RecvPropVector( RECVINFO(m_vecDirection)),
	RecvPropInt( RECVINFO(r)),
	RecvPropInt( RECVINFO(g)),
	RecvPropInt( RECVINFO(b)),
	RecvPropInt( RECVINFO(a)),
	RecvPropInt( RECVINFO(m_nAmount)),
END_RECV_TABLE()


//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
C_TEBloodStream::C_TEBloodStream( void )
{
	m_vecOrigin.Init();
	m_vecDirection.Init();
	r = g = b = a = 0;
	m_nAmount = 0;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
C_TEBloodStream::~C_TEBloodStream( void )
{
}


//-----------------------------------------------------------------------------
// Recording 
//-----------------------------------------------------------------------------
static inline void RecordBloodStream( const Vector &start, const Vector &direction, 
	int r, int g, int b, int a, int amount )
{
	if ( !ToolsEnabled() )
		return;

	if ( clienttools->IsInRecordingMode() )
	{
		Color clr( r, g, b, a );

		KeyValues *msg = new KeyValues( "TempEntity" );

 		msg->SetInt( "te", TE_BLOOD_STREAM );
 		msg->SetString( "name", "TE_BloodStream" );
		msg->SetFloat( "time", gpGlobals->curtime );
		msg->SetFloat( "originx", start.x );
		msg->SetFloat( "originy", start.y );
		msg->SetFloat( "originz", start.z );
		msg->SetFloat( "directionx", direction.x );
		msg->SetFloat( "directiony", direction.y );
		msg->SetFloat( "directionz", direction.z );
		msg->SetColor( "color", clr );
		msg->SetInt( "amount", amount );

		ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
		msg->deleteThis();
	}
}


void TE_BloodStream( IRecipientFilter& filter, float delay,
	const Vector* org, const Vector* direction, int r, int g, int b, int a, int amount )
{
	RecordBloodStream( *org, *direction, r, g, b, a, amount );

	CSmartPtr<CTEParticleRenderer> pRen = CTEParticleRenderer::Create( "TEBloodStream", *org );
	if( !pRen )
		return;

	// Add our particles.
	Vector		dirCopy;
	float		arc = 0.05;
	int			count, count2;
	float		num;
	float		speedCopy = amount;
	
	Vector dir;
	VectorCopy( *direction, dir );
	VectorNormalize( dir );
	
	for (count=0 ; count<100 ; count++)
	{
		StandardParticle_t *p = pRen->AddParticle();
		if(p)
		{
			p->SetColor(r * random->RandomFloat(0.7, 1.0), g, b);
			p->SetAlpha(a);
			p->m_Pos = *org;
			pRen->SetParticleLifetime(p, 2);
			pRen->SetParticleType(p, pt_vox_grav);
			
			VectorCopy (dir, dirCopy);
			
			dirCopy[2] -= arc;
			arc -= 0.005;
			
			VectorScale (dirCopy, speedCopy, p->m_Velocity);
			
			speedCopy -= 0.00001;// so last few will drip
		}
	}
	
	// now a few rogue voxels
	arc = 0.075;
	for (count = 0 ; count < (amount/5); count ++)
	{
		StandardParticle_t *p = pRen->AddParticle();
		if(p)
		{
			pRen->SetParticleLifetime(p, 3);
			p->SetColor(r * random->RandomFloat(0.7, 1.0), g, b);
			p->SetAlpha(a);
			p->m_Pos = *org;
			pRen->SetParticleType(p, pt_vox_slowgrav);
			
			VectorCopy (dir, dirCopy);
			
			dirCopy[2] -= arc;
			arc -= 0.005;
			
			num = random->RandomFloat(0,1);
			speedCopy = amount * num;
			
			num *= 1.7;
			
			VectorScale (dirCopy, num, dirCopy);// randomize a bit
			p->m_Velocity = dirCopy * speedCopy;
			
			
			// add a few extra voxels directly adjacent to this one to give a 
			// 'chunkier' appearance.
			for (count2 = 0; count2 < 2; count2++)
			{
				StandardParticle_t *p = pRen->AddParticle();
				if(p)
				{
					pRen->SetParticleLifetime(p, 3);
					p->SetColor(random->RandomFloat(0.7, 1.0), g, b);
					p->SetAlpha(a);
					p->m_Pos.Init(
						(*org)[0] + random->RandomFloat(-1,1),
						(*org)[1] + random->RandomFloat(-1,1),
						(*org)[2] + random->RandomFloat(-1,1));
					
					pRen->SetParticleType(p, pt_vox_slowgrav);
					
					VectorCopy (dir, dirCopy);
					
					dirCopy[2] -= arc;
					
					VectorScale (dirCopy, num, dirCopy);// randomize a bit
					
					p->m_Velocity = dirCopy * speedCopy;
				}
			}
		}
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_TEBloodStream::PostDataUpdate( DataUpdateType_t updateType )
{
	CBroadcastRecipientFilter filter;
	TE_BloodStream( filter, 0.0f, &m_vecOrigin, &m_vecDirection, r, g, b, a, m_nAmount );
}

void TE_BloodStream( IRecipientFilter& filter, float delay, KeyValues *pKeyValues )
{
	Vector vecOrigin, vecDirection;
	vecOrigin.x = pKeyValues->GetFloat( "originx" );
	vecOrigin.y = pKeyValues->GetFloat( "originy" );
	vecOrigin.z = pKeyValues->GetFloat( "originz" );
	vecDirection.x = pKeyValues->GetFloat( "directionx" );
	vecDirection.y = pKeyValues->GetFloat( "directiony" );
	vecDirection.z = pKeyValues->GetFloat( "directionz" );
	Color c = pKeyValues->GetColor( "color" );
	int nAmount = pKeyValues->GetInt( "amount" );
	TE_BloodStream( filter, 0.0f, &vecOrigin, &vecDirection, c.r(), c.g(), c.b(), c.a(), nAmount );
}