//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
//=============================================================================
#include "cbase.h"	   
#include "c_te_particlesystem.h"
#include "movevars_shared.h"

int		ramp1[][3] =
{
	{ 255, 243, 227 },
	{ 223, 171, 39 },
	{ 191, 119, 47 },
	{ 127, 59, 43 },
	{ 99, 47, 31 },
	{ 75, 35, 19 },
	{ 47, 23, 11 },
	{ 175, 103, 35 },
};

int		ramp2[][3] =
{
	{ 255, 243, 227 },
	{ 239, 203, 31 },
	{ 223, 171, 39 },
	{ 207, 143, 43 },
	{ 191, 119, 47 },
	{ 175, 99, 47 },
	{ 143, 67, 51 },
	{ 115, 55, 35 },
};

int		ramp3[][3] =
{
	{ 223, 171, 39 },
	{ 191, 119, 47 },
	{ 91, 91, 91 },
	{ 75, 75, 75 },
	{ 63, 63, 63 },
	{ 47, 47, 47 },
};

#define SPARK_COLORCOUNT	9

int		gSparkRamp[ SPARK_COLORCOUNT ][3] =
{
	{ 255, 255, 255 },
	{ 255, 247, 199 },
	{ 255, 243, 147 },
	{ 255, 243, 27 },
	{ 239, 203, 31 },
	{ 223, 171, 39 },
	{ 207, 143, 43 },
	{ 127, 59, 43 },
	{ 35, 19, 7 }
};



// ------------------------------------------------------------------------ //
// C_TEParticleSystem.
// ------------------------------------------------------------------------ //

IMPLEMENT_CLIENTCLASS_DT(C_TEParticleSystem, DT_TEParticleSystem, CTEParticleSystem)
	RecvPropVector( RECVINFO(m_vecOrigin)),
END_RECV_TABLE()


C_TEParticleSystem::C_TEParticleSystem()
{
	m_vecOrigin.Init();
}



// ------------------------------------------------------------------------ //
// CTEParticleRenderer implementation.
// ------------------------------------------------------------------------ //

CTEParticleRenderer::CTEParticleRenderer( const char *pDebugName ) :
	CParticleEffect( pDebugName )
{
	m_ParticleSize = 1.5f;
	m_MaterialHandle = INVALID_MATERIAL_HANDLE;
}


CTEParticleRenderer::~CTEParticleRenderer()
{
}


CSmartPtr<CTEParticleRenderer> CTEParticleRenderer::Create( const char *pDebugName, const Vector &vOrigin )
{
	CTEParticleRenderer *pRet = new CTEParticleRenderer( pDebugName );
	if( pRet )
	{
		pRet->SetDynamicallyAllocated( true );
		pRet->SetSortOrigin( vOrigin );
	}

	return pRet;
}


StandardParticle_t* CTEParticleRenderer::AddParticle()
{
	if(m_MaterialHandle == INVALID_MATERIAL_HANDLE)
	{
		m_MaterialHandle = m_ParticleEffect.FindOrAddMaterial("particle/particledefault");
	}

	StandardParticle_t *pParticle = 
		(StandardParticle_t*)BaseClass::AddParticle( sizeof(StandardParticle_t), m_MaterialHandle, m_vSortOrigin );

	if(pParticle)
		pParticle->m_EffectDataWord = 0; // (ramp)

	return pParticle;
}


bool CTEParticleRenderer::SimulateAndRender(Particle *pBaseParticle, ParticleDraw *pDraw, float &sortKey)
{
	StandardParticle_t* pParticle = (StandardParticle_t*)pBaseParticle;

	// Remove the particle?
	SetParticleLifetime(pParticle, GetParticleLifetime(pParticle) - pDraw->GetTimeDelta());
	if(GetParticleLifetime(pParticle) < 0)
		return false;

	float	ft = pDraw->GetTimeDelta();
	float	time3 = 15.0 * ft;
	float	time2 = 10.0 * ft;
	float	time1 = 5.0 * ft;
	float	dvel = 4* ft ;

	float grav = ft * sv_gravity.GetFloat() * 0.05f;

	int		(*colorIndex)[3];
	int		iRamp;

	switch(GetParticleType(pParticle))
	{
	case pt_static:
		break;

	case pt_fire:
		pParticle->m_EffectDataWord += (unsigned short)(time1 * (1 << SIMSHIFT));
		iRamp = pParticle->m_EffectDataWord >> SIMSHIFT;
		if(iRamp >= 6)
		{
			pParticle->m_Lifetime = -1;
		}
		else
		{
			colorIndex = &ramp3[ iRamp ];
			pParticle->SetColor((float)(*colorIndex)[0] / 255.0f, (float)(*colorIndex)[1] / 255.0f, (float)(*colorIndex)[2] / 255.0f);
		}
		pParticle->m_Velocity[2] += grav;
		break;

	case pt_explode:
		pParticle->m_EffectDataWord += (unsigned short)(time2 * (1 << SIMSHIFT));
		iRamp = pParticle->m_EffectDataWord >> SIMSHIFT;
		if(iRamp >= 8)
		{
			pParticle->m_Lifetime = -1;
		}
		else
		{
			colorIndex = &ramp1[ iRamp ];
			pParticle->SetColor((float)(*colorIndex)[0] / 255.0f, (float)(*colorIndex)[1] / 255.0f, (float)(*colorIndex)[2] / 255.0f);
		}
		pParticle->m_Velocity = pParticle->m_Velocity + pParticle->m_Velocity * dvel;
		pParticle->m_Velocity[2] -= grav;
		break;

	case pt_explode2:
		pParticle->m_EffectDataWord += (unsigned short)(time3 * (1 << SIMSHIFT));
		iRamp = pParticle->m_EffectDataWord >> SIMSHIFT;
		if(iRamp >= 8)
		{
			pParticle->m_Lifetime = -1;
		}
		else
		{
			colorIndex = &ramp2[ iRamp ];
			pParticle->SetColor((float)(*colorIndex)[0] / 255.0f, (float)(*colorIndex)[1] / 255.0f, (float)(*colorIndex)[2] / 255.0f);
		}
		pParticle->m_Velocity = pParticle->m_Velocity - pParticle->m_Velocity * ft;
		pParticle->m_Velocity[2] -= grav;
		break;

	case pt_grav:
		pParticle->m_Velocity[2] -= grav * 20;
		break;
	case pt_slowgrav:
		pParticle->m_Velocity[2] = grav;
		break;

	case pt_vox_grav:
		pParticle->m_Velocity[2] -= grav * 8;
		break;
		
	case pt_vox_slowgrav:
		pParticle->m_Velocity[2] -= grav * 4;
		break;

		
	case pt_blob:
	case pt_blob2:
		pParticle->m_EffectDataWord += (unsigned short)(time2 * (1 << SIMSHIFT));
		iRamp = pParticle->m_EffectDataWord >> SIMSHIFT;
		if(iRamp >= SPARK_COLORCOUNT)
		{
			pParticle->m_EffectDataWord = 0;
			iRamp = 0;
		}
		
		colorIndex = &gSparkRamp[ iRamp ];
		pParticle->SetColor((float)(*colorIndex)[0] / 255.0f, (float)(*colorIndex)[1] / 255.0f, (float)(*colorIndex)[2] / 255.0f);
		
		pParticle->m_Velocity[0] -= pParticle->m_Velocity[0]*0.5*ft;
		pParticle->m_Velocity[1] -= pParticle->m_Velocity[1]*0.5*ft;
		pParticle->m_Velocity[2] -= grav * 5;

		if ( random->RandomInt(0,3) )
		{
			SetParticleType(pParticle, pt_blob);
			pParticle->SetAlpha(0);
		}
		else
		{
			SetParticleType(pParticle, pt_blob2);
			pParticle->SetAlpha(255.9f);
		}
		break;
	}

	// Render.
	Vector tPos;
	TransformParticle(g_ParticleMgr.GetModelView(), pParticle->m_Pos, tPos);
	sortKey = tPos.z;

	Vector vColor(pParticle->m_Color[0]/255.9f, pParticle->m_Color[1]/255.9f, pParticle->m_Color[2]/255.9f);
	RenderParticle_ColorSize(
		pDraw,
		tPos,
		vColor,
		pParticle->m_Color[3]/255.9f,
		m_ParticleSize);
			
	// Update position.
	pParticle->m_Pos = pParticle->m_Pos + pParticle->m_Velocity * ft;
	return true;
}

