// Fetch template if we have a valid template index, create a new custom template if we don't
AvHParticleTemplate*
AvHParticleSystemEntity::GetCustomTemplate()
{
	AvHParticleTemplate* theTemplate = NULL;

	if(!this->mCreatedTemplate)
	{
		if(this->mTemplateIndex == -1)
		{
			// Create a new template, none was specified in the name field
			ASSERT(!this->mCreatedTemplate);
			this->mTemplateIndex = gParticleTemplateList.CreateTemplateFromIndex();
		}
		//else
		//{
		//	// Create a template from our existing base template
		//	this->mTemplateIndex = gParticleTemplateList.CreateTemplateFromIndex(this->mTemplateIndex);
		//}
		
		// Set the name of our new custom particle system
		theTemplate = gParticleTemplateList.GetTemplateAtIndex(this->mTemplateIndex);
		ASSERT(theTemplate);
		string theName = STRING(this->pev->targetname);
		theTemplate->SetName(theName);
		
		this->mCreatedTemplate = true;
	}
	
	ASSERT(this->mTemplateIndex != -1);
	if(!theTemplate)
		theTemplate = gParticleTemplateList.GetTemplateAtIndex(this->mTemplateIndex);
	
	return theTemplate;
}
void
AvHParticleSystemEntity::Spawn( void )
{
	// Just in case our class derives off of something else in the future
	CBaseEntity::Spawn();
	
	this->Precache();
	
	this->pev->classname = MAKE_STRING(kesParticlesCustom);
	this->pev->solid = SOLID_NOT;
	this->pev->movetype = MOVETYPE_NONE;
	//this->pev->movetype = MOVETYPE_PUSH;
	//this->pev->effects = EF_BRIGHTLIGHT;
	
	this->SetTouch(&AvHParticleSystemEntity::ParticleTouch);
	this->SetUse(&AvHParticleSystemEntity::ParticleUse);
	
	SET_MODEL(ENT(this->pev), kNullModel);
	UTIL_SetOrigin(this->pev, this->pev->origin);
	
	// Set the other flags
	AvHParticleTemplate* theTemplate = gParticleTemplateList.GetTemplateAtIndex(this->mTemplateIndex);
	//ASSERT(theTemplate);
	if(theTemplate)
	{
		//theTemplate->SetFlags(theSpawnFlags);
		
		string theTargetName = STRING(this->pev->targetname);
		if(!FStrEq(theTargetName.c_str(), ""))
		{
			theTemplate->SetName(theTargetName);
		}
		
		this->SetThink(&AvHParticleSystemEntity::ParticleThink);
		pev->nextthink = gpGlobals->time + kDefaultParticleSystemThinkRate;
		
		// The spawn flags field is the only one that doesn't get set through KeyValue(), so
		// we set it in the template this way
		int theSpawnFlags = this->pev->spawnflags;
		if(!theSpawnFlags)
		{
			theSpawnFlags = theTemplate->GetFlags();
		}

		// Did they check the "start on" flag?
		if(theSpawnFlags & 1)
		{
			this->mUseState = true;
		}

		theTemplate->SetFlags(theSpawnFlags);
	}
	else
	{
		ALERT(at_logged, "Couldn't find particle system template: %d\n", this->mTemplateIndex);
		UTIL_Remove(this);
	}
}
int	AvHParticleTemplateListClient::InitializeDemoPlayback(int inSize, unsigned char* inBuffer, int index)
{
	// Read one particle template and add it to the list
	int theBytesRead = 0;

	AvHParticleTemplate theTemplate;

	// Read all fields
	string theTemplateName;
	LoadStringData(theTemplateName, inBuffer, theBytesRead);
	theTemplate.SetName(theTemplateName);

	uint32 theMaxParticles;
	LOAD_DATA(theMaxParticles);
	theTemplate.SetMaxParticles(theMaxParticles);

	float theParticleSize;
	LOAD_DATA(theParticleSize);
	theTemplate.SetParticleSize(theParticleSize);

	float theParticleSystemLifetime;
	LOAD_DATA(theParticleSystemLifetime);
	theTemplate.SetParticleSystemLifetime(theParticleSystemLifetime);
	
	float theParticleLifetime;
	LOAD_DATA(theParticleLifetime);
	theTemplate.SetParticleLifetime(theParticleLifetime);
	
	string theSpriteName;
	LoadStringData(theSpriteName, inBuffer, theBytesRead);
	theTemplate.SetSprite(theSpriteName);

	ShapeType theGenerationShape;
	LOAD_DATA(theGenerationShape);
	theTemplate.SetGenerationShape(theGenerationShape);

	string theGenerationEntityName;
	LoadStringData(theGenerationEntityName, inBuffer, theBytesRead);
	theTemplate.SetGenerationEntityName(theGenerationEntityName);

	string theParticleSystemToGenerate;
	LoadStringData(theParticleSystemToGenerate, inBuffer, theBytesRead);
	theTemplate.SetParticleSystemToGenerate(theParticleSystemToGenerate);

	int theParticleSystemIndexToGenerate;
	LOAD_DATA(theParticleSystemIndexToGenerate);
	theTemplate.SetParticleSystemIndexToGenerate(theParticleSystemIndexToGenerate);

	int theGenerationEntityIndex;
	LOAD_DATA(theGenerationEntityIndex);
	theTemplate.SetGenerationEntityIndex(theGenerationEntityIndex);
	
	float theGenerationEntityParameter;
	LOAD_DATA(theGenerationEntityParameter);
	theTemplate.SetGenerationEntityParameter(theGenerationEntityParameter);

	ShapeType theStartingVelocityShape;
	LOAD_DATA(theStartingVelocityShape);
	theTemplate.SetStartingVelocityShape(theStartingVelocityShape);

	ParticleParams theGenerationParams;
	LOAD_DATA(theGenerationParams);
	theTemplate.SetGenerationParams(theGenerationParams);

	ParticleParams theStartingVelocityParams;
	LOAD_DATA(theStartingVelocityParams);
	theTemplate.SetStartingVelocityParams(theStartingVelocityParams);

	uint32 theGenerationRate;
	LOAD_DATA(theGenerationRate);
	theTemplate.SetGenerationRate(theGenerationRate);

	int theParticleFlags;
	LOAD_DATA(theParticleFlags);
	theTemplate.SetFlags(theParticleFlags);

	PSVector theGravity;
	LOAD_DATA(theGravity);
	theTemplate.SetGravity(theGravity);

	float theAnimationSpeed;
	LOAD_DATA(theAnimationSpeed);
	theTemplate.SetAnimationSpeed(theAnimationSpeed);

	int theNumSpriteFrames;
	LOAD_DATA(theNumSpriteFrames);
	theTemplate.SetNumSpriteFrames(theNumSpriteFrames);

	float theParticleScaling;
	LOAD_DATA(theParticleScaling);
	theTemplate.SetParticleScaling(theParticleScaling);

	int theRenderMode;
	LOAD_DATA(theRenderMode);
	theTemplate.SetRenderMode(theRenderMode);

	float theMaxAlpha;
	LOAD_DATA(theMaxAlpha);
	theTemplate.SetMaxAlpha(theMaxAlpha);

	// Save the template
	this->mTemplateList[index]=theTemplate;

	return theBytesRead;
}
void
AvHParticleSystemEntity::UpdateClientData()
{
	// Turn the system on or off
	if(this->mIsOn != this->mUseState)
	{
		this->mIsOn = this->mUseState;
		
		// set up entity so it's propagated correctly
		if(this->mIsOn)
		{
			// TODO: Reset sCurrentHandle to 1 every time a new game starts?
			this->mHandle = sCurrentHandle++;
			
			// Create server side system for collision only
			int theEntIndex = this->entindex();
			AvHParticleSystemManager::Instance()->CreateParticleSystemIfNotCreated(theEntIndex, this->mTemplateIndex, this->mHandle);
			
			// Replicate action to everyone
			this->pev->iuser3 = AVH_USER3_PARTICLE_ON;
			const AvHParticleTemplate* theTemplate = gParticleTemplateList.GetTemplateAtIndex(this->mTemplateIndex);
			ASSERT(theTemplate);
				
			int theGenEntityIndex = theTemplate->GetGenerationEntityIndex();
			if(theGenEntityIndex == -1)
			{
				theGenEntityIndex = 0;
			}

			//this->pev->fuser1 = /*this->mTemplateIndex;*/ (theGenEntityIndex << 16) | this->mTemplateIndex;

			ASSERT(this->mTemplateIndex < 256);
			this->pev->fuser1 = (theGenEntityIndex << 16) | ((this->mTemplateIndex & 0xFF) << 8);
			this->pev->fuser2 = this->mHandle;

			// Store our custom data
			this->SetCustomData(this->mCustomData);
			
			this->mTimeParticlesCreated = gpGlobals->time;
		}
		else
		{
			// Destroy server side particle system
			//AvHParticleSystemManager::Instance()->DestroyParticleSystemIfNotDestroyed(this->entindex(), this->mHandle);
			AvHParticleSystemManager::Instance()->MarkParticleSystemForDeletion(this->entindex(), this->mHandle);
			
			// Replicate action to everyone
			this->pev->iuser3 = AVH_USER3_PARTICLE_OFF;
			this->pev->fuser1 = this->mHandle;
		}
	}
	
	if(this->mIsOn)
	{
		AvHParticleTemplate* theTemplate = gParticleTemplateList.GetTemplateAtIndex(this->mTemplateIndex);
		ASSERT(theTemplate);
		
		// If particle system was set to expire, make sure to realize when it turns off
		int theParticleSystemLifetime = theTemplate->GetParticleSystemLifetime();
		if(theParticleSystemLifetime != -1)
		{
			if(gpGlobals->time - this->mTimeParticlesCreated >= theParticleSystemLifetime)
			{
				//this->mIsOn = false;
				this->mUseState = false;
			}
		}
	}
}