//
// Asura_ClientEntity_PFX_Effect.cpp
//
// Created by KOR - 15/03/2004 10:56:21
//
// Copyright (C) 2004 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"


// This file's header.
#include "Entity/ParticleGenerator/Asura_ClientEntity_PFX_Effect.h"

// Asura includes
#include "Core/Asura_Timers.h"
#include "Entity/Asura_Entity_Classification.h"
#include "Entity/ParticleGenerator/Asura_ServerEntity_PFX_Effect.h"
#include "Network/Asura_Message.h"
#include "SpecialFX/PFX/Asura_PFX_Entity_Effect.h"
#include "SpecialFX/PFX/Asura_PFX_System.h"
#include "SpecialFX/PFX/Asura_PFX_Templates.h"

// Tools includes
#ifdef ASURA_TOOLS
#include "Entity/Tools_Entity_Data.h"
#include "EntityTemplate/Tools_EntityTemplate_System.h"
#include "Particles/Tools_Mode_PFX.h"
#endif

Asura_Hashed_List<Asura_ClientEntity_PFX_Effect> Asura_ClientEntity_PFX_Effect::s_xList( 5 );

#ifdef ASURA_TOOLS
Asura_ClientEntity_PFX_Effect::Asura_ClientEntity_PFX_Effect(const Asura_Vector_3& xPos, const Asura_Matrix_3x3& xDir, Asura_Hash_ID uTemplateHash)
: Asura_Entity_Client()
, m_iEffectID(ASURA_PFX_INVALID_EFFECT_ID)
, m_fStartTime(0.0f)
, m_fTriggerTimer(0.0f)
, m_bUseEffectSpecificRNG(false)
, m_bSelectedInTools(false)
, m_bStartsActive(false)
{
	m_xCurrentPosition = xPos;
	m_xCurrentOrientation = xDir;
	Classification = AsuraEntityClass_PFX_Effect;

	s_xList.AddToList(this);
}
#endif // ASURA_TOOLS

Asura_ClientEntity_PFX_Effect::Asura_ClientEntity_PFX_Effect()
: Asura_Entity_Client()
, m_iEffectID(ASURA_PFX_INVALID_EFFECT_ID)
, m_fStartTime(0.0f)
, m_fTriggerTimer(0.0f)
#ifdef ASURA_TOOLS
, m_bUseEffectSpecificRNG(false)
, m_bSelectedInTools(false)
, m_bStartsActive(false)
#endif
{
	//Set the chunk type for this entity
	Classification = AsuraEntityClass_PFX_Effect;

	s_xList.AddToList( this );
}

Asura_ClientEntity_PFX_Effect::~Asura_ClientEntity_PFX_Effect(void)
{
	StopEffect(true);
	s_xList.RemoveFromList( this );
}

void Asura_ClientEntity_PFX_Effect::ReadFromChunkStream(Asura_Chunk_Stream& xStream)
{
	//Extract version number from chunk
	int iChunkVersion;
	xStream >> iChunkVersion;

	//skip parent class data
	bool bActive = false;
	Asura_Entity_Server::SkippedServerData xSkippedData;
	xSkippedData.m_bActive			= false;
	xSkippedData.m_bTemplateActive	= false;
	if(iChunkVersion >= 9)
	{
		Asura_Entity_Server::SkipDataInChunkStream(xStream, &xSkippedData);
	}
	
	if(iChunkVersion >= 10)
	{
		m_xPFXEffectData.ReadFromChunkStream(xStream, m_xCurrentPosition, m_xCurrentOrientation);
		xStream >> m_fStartTime;
		bActive = m_xPFXEffectData.m_bOldActiveFlag;
	}
	else if(iChunkVersion == 8 || iChunkVersion == 9)
	{
		Asura_Entity_PFX_Effect_ChunkData xChunkData;
		// Extract attributes
		xStream.Read(sizeof(Asura_Entity_PFX_Effect_ChunkData), &xChunkData);
		m_xCurrentPosition = xChunkData.m_xPosition;

		Asura_Quat xTempQuat;
		xChunkData.m_xOrientation.ToQuat(xTempQuat);
		xTempQuat.ToMatrix(m_xCurrentOrientation);

		m_xPFXEffectData.m_uEffectTemplateHash = xChunkData.m_uEffectTemplateHash;

		// Collision plane data
		m_xPFXEffectData.m_xCollisionPosition = xChunkData.m_xCollisionPosition;
		m_xPFXEffectData.m_xCollisionDirection = xChunkData.m_xCollisionDirection;
		bActive = xChunkData.m_bOldActiveFlag;

		m_fStartTime = xChunkData.m_fTimeSinceLastActivateMessage;

		if(xChunkData.m_bIgnoreModuleLinking)
		{
			m_xPFXEffectData.m_bIgnoreModuleLinking = true;
		}
		if(xChunkData.m_bSkyboxEffect)
		{
			m_xPFXEffectData.m_bSkyboxEffect = true;
		}
		if(xChunkData.m_bWaterDistorterEffect)
		{
			m_xPFXEffectData.m_bWaterDistorterEffect = true;			
		}

		m_xPFXEffectData.m_fMinRetriggerTime = xChunkData.m_fMinRetriggerTime;
		m_xPFXEffectData.m_fMaxRetriggerTime = xChunkData.m_fMaxRetriggerTime;

		m_xPFXEffectData.m_xSourceVolume.ReadFromChunkStream(xStream);
	}
#ifdef ASURA_TOOLS
	else if(iChunkVersion == 7)
	{
		Asura_Entity_PFX_Effect_ChunkData_V7 xChunkData;
		// Extract attributes
		xStream.Read(sizeof(Asura_Entity_PFX_Effect_ChunkData_V7), &xChunkData);
		m_xCurrentPosition = xChunkData.m_xPosition;

		Asura_Quat xTempQuat;
		xChunkData.m_xOrientation.ToQuat(xTempQuat);
		xTempQuat.ToMatrix(m_xCurrentOrientation);

		m_xPFXEffectData.m_uEffectTemplateHash = xChunkData.m_uEffectTemplateHash;

		// Collision plane data
		m_xPFXEffectData.m_xCollisionPosition = xChunkData.m_xCollisionPosition;
		m_xPFXEffectData.m_xCollisionDirection = xChunkData.m_xCollisionDirection;
		bActive = xChunkData.m_bOldActiveFlag;

		m_fStartTime = xChunkData.m_fTimeSinceLastActivateMessage;

		if(xChunkData.m_bIgnoreModuleLinking)
		{
			m_xPFXEffectData.m_bIgnoreModuleLinking = true;
		}
		if(xChunkData.m_bSkyboxEffect)
		{
			m_xPFXEffectData.m_bSkyboxEffect = true;
		}

		m_xPFXEffectData.m_xSourceVolume.ReadFromChunkStream(xStream);
	}
	else if(iChunkVersion == 5 || iChunkVersion == 6)
	{
		Asura_Entity_PFX_Effect_ChunkData_V6 xChunkData;
		// Extract attributes
		xStream.Read(sizeof(Asura_Entity_PFX_Effect_ChunkData_V6), &xChunkData);
		m_xCurrentPosition = xChunkData.m_xPosition;

		Asura_Quat xTempQuat;
		if(iChunkVersion==5)
		{
			//version 5 used Asura_Comp_Quat instead of Asura_Comp_Quat_Fast
			((Asura_Comp_Quat*)&xChunkData.m_xOrientation)->ToQuat(xTempQuat);
		}
		else
		{
			xChunkData.m_xOrientation.ToQuat(xTempQuat);
		}
		xTempQuat.ToMatrix(m_xCurrentOrientation);

		m_xPFXEffectData.m_uEffectTemplateHash = xChunkData.m_uEffectTemplateHash;

		// Collision plane data
		m_xPFXEffectData.m_xCollisionPosition = xChunkData.m_xCollisionPosition;
		m_xPFXEffectData.m_xCollisionDirection = xChunkData.m_xCollisionDirection;
		bActive = xChunkData.m_bOldActiveFlag;

		m_fStartTime = 0.0f;

		if(xChunkData.m_bIgnoreModuleLinking)
		{
			m_xPFXEffectData.m_bIgnoreModuleLinking = true;
		}
		if(xChunkData.m_bSkyboxEffect)
		{
			m_xPFXEffectData.m_bSkyboxEffect = true;
		}

		m_xPFXEffectData.m_xSourceVolume.ReadFromChunkStream(xStream);
	}
	else if( 0 < iChunkVersion && iChunkVersion < 5 )
	{
		Asura_Entity_PFX_Effect_ChunkData_V1 xChunkData;
		// Extract attributes
		xStream.Read(sizeof(Asura_Entity_PFX_Effect_ChunkData_V1), &xChunkData);
		m_xCurrentPosition = xChunkData.m_xPosition;
		m_xCurrentOrientation = xChunkData.m_xOrientation;
		m_xPFXEffectData.m_uEffectTemplateHash = xChunkData.m_uEffectTemplateHash;

		// Collision plane data
		m_xPFXEffectData.m_xCollisionPosition = xChunkData.m_xCollisionPosition;
		m_xPFXEffectData.m_xCollisionDirection = xChunkData.m_xCollisionDirection;
		bActive = xChunkData.m_bOldActiveFlag;
		if(iChunkVersion >=4)
		{
			if(xChunkData.m_bIgnoreModuleLinking)
			{
				m_xPFXEffectData.m_bIgnoreModuleLinking = true;
			}
		}

		m_fStartTime = 0.0f;

		if(iChunkVersion >= 2)
		{
			m_xPFXEffectData.m_xSourceVolume.ReadFromChunkStream(xStream);
		}
	}
#endif
	else
	{
		Asura_Assert( false, "Unsupported chunk version" );
	}

	if(iChunkVersion >= 11)
	{
		//active flag is taken from the parent class server data for more recent versions
		//RAR  14/03/2008
		bActive = xSkippedData.m_bActive && xSkippedData.m_bTemplateActive;
	}

	SetEntityActiveFromLoad(bActive);
#ifdef ASURA_TOOLS
	m_bStartsActive = bActive;
#endif

	if(IsRandomRetrigger() && bActive && !IsUpdateable())
	{
		// Need to update random re-trigger effects.
		AddToUpdateableClientList(this);
	}
}

bool Asura_ClientEntity_PFX_Effect::HandleMessage(const Asura_Message* pxMessage)
{
	if( pxMessage )	
	{
		switch( pxMessage->GetMsgID() )
		{
			case ASURA_MSG_ACTIVATE:
			{
				Activate(true);
				return true;
			}

			case ASURA_MSG_DEACTIVATE:
			{
				Activate(false);
				return true;
			}

			case ASURA_MSG_DESTRUCT:
			{
				StopEffect(true);
				SetAsDestroyed();
				return true;
			}

			default :
			{				
				break;
			}
		}
	}
	
	return PARENT::HandleMessage( pxMessage );
}

void Asura_ClientEntity_PFX_Effect::PostCreateInitialise()
{
	if(IsEntityActive())
	{
		StartEffect();
	}
}

void Asura_ClientEntity_PFX_Effect::Update()
{
	Asura_Assert(IsRandomRetrigger() && IsEntityActive(), "Should only be updating active random re-trigger effects");

	if(m_iEffectID == ASURA_PFX_INVALID_EFFECT_ID)
	{
		m_fTriggerTimer -= Asura_Timers::GetGameTimeSlice();
		if(m_fTriggerTimer <= 0.f)
		{
			StartEffect();
		}
	}
	else
	{
		const Asura_PFX_Entity_Effect* pxEffect = GetCurrentEffect();
		if(!pxEffect)
		{
			m_iEffectID = ASURA_PFX_INVALID_EFFECT_ID;
			//get time till next trigger
			m_fTriggerTimer = Asura_Random::GetFloat(m_xPFXEffectData.m_fMinRetriggerTime,m_xPFXEffectData.m_fMaxRetriggerTime);
		}
	}
}

u_int Asura_ClientEntity_PFX_Effect::CreateEffect(const Asura_Vector_3& xPosition, const Asura_Matrix_3x3& xDirection, Asura_Hash_ID uTemplate, const Asura_PFX_Volume* pxVolumeOverride)
{
	const u_int uEffectID = Asura_PFX_Entity_Effect::Create(xPosition, xDirection, uTemplate, pxVolumeOverride, ASURA_PFX_EFFECT_CAMERA_FLAGS, GetGuid());
	Asura_Assertf( (uEffectID != ASURA_PFX_INVALID_EFFECT_ID), ("Failed to create effect for PFX effect entity '%d'. Looking for PFX template with ID '%x'", GetGuid(), uTemplate ));
	return uEffectID;
}

void Asura_ClientEntity_PFX_Effect::StartEffect()
{
	if (m_iEffectID != ASURA_PFX_INVALID_EFFECT_ID)
	{
		StopEffect(true);
	}
	m_fTriggerTimer = 0.0f;

#ifdef ASURA_TOOLS
	// Template hasn't been chosen yet
	if(!m_xPFXEffectData.m_uEffectTemplateHash) return;
#else
	Asura_Assert(m_xPFXEffectData.m_uEffectTemplateHash, "No template");
#endif

#ifdef ASURA_TOOLS
	//Check to see whether the entity is supposed to be included for the current preview platform.
	//Unfortunately this means we have to find the server entity to check. RAR 07/09/2005
	Asura_ServerEntity_PFX_Effect* pxServerEntity = Asura_ServerEntity_PFX_Effect::FindEntity(Guid);
	if(pxServerEntity && pxServerEntity->ToolsData)
	{
		if(!pxServerEntity->ToolsData->ShouldExportToPlatform(Tools_Mode_PFX::GetPreviewPlatform()))
		{
			return;//not for the current platform then
		}
	}
#endif

	// AJG - 09/02/06 - If we have a start time, check if this time is actually still within the lifespan of the effect
	// Keep the pointer around, we may need it later and we might as well avoid doing the lookup twice.
	// RAR 22/06/06 - Ignore the start time if randomly retriggering.
	const Asura_PFX_Effect_Template* pxEffectTemplate = Asura_PFX_System::GetEffectTempByHash(m_xPFXEffectData.m_uEffectTemplateHash);
	if (m_fStartTime > 0.0f && !IsRandomRetrigger())
	{
		if (pxEffectTemplate)
		{
			if (pxEffectTemplate->m_bLooping)
			{
				// Looping ones by definition will always start. Adjust start time to the correct point.
				m_fStartTime = Asura_Maths::FloatMod(m_fStartTime, pxEffectTemplate->m_fLifeTime);
			}
			else if (m_fStartTime >= pxEffectTemplate->m_fLifeTime)
			{
				// This is a one-shot effect that's passed the end, set ourselves as finished
				SetEntityActive(false);
				return;
			}
		}
	}

	//create the particle effect
	Asura_PFX_Volume* pxVolume = NULL;
	if(m_xPFXEffectData.m_xSourceVolume.m_eType != ASURA_PFX_VOLUME_POINT)
	{
		pxVolume = &m_xPFXEffectData.m_xSourceVolume;
	}
	m_iEffectID = CreateEffect(m_xCurrentPosition, m_xCurrentOrientation, m_xPFXEffectData.m_uEffectTemplateHash, pxVolume);
	SetEntityActive(true);

	Asura_PFX_Entity_Effect* pxEffect = (Asura_PFX_Entity_Effect*)Asura_PFX_System::GetEffect(m_iEffectID);
	if(pxEffect)
	{
		#ifdef ASURA_TOOLS
		//Use our RNG if flagged to do so (as a result of recording a cutscene AVI). RAR 22/05/2006
		if(m_bUseEffectSpecificRNG)
		{
			pxEffect->SetRNG(&m_xEffectSpecificRNG);
		}

		//mark as selected if needed ,so that it gets added the selected particle count. RAR 22/01/2007
		pxEffect->SetSelectedInTools(m_bSelectedInTools);
		#endif
		
		pxEffect->SetCollisionPlane(m_xPFXEffectData.m_xCollisionPosition, m_xPFXEffectData.m_xCollisionDirection);
		pxEffect->SetIgnoreModuleLinking(m_xPFXEffectData.m_bIgnoreModuleLinking);
		pxEffect->SetSkyboxEffect(m_xPFXEffectData.m_bSkyboxEffect);
		pxEffect->SetWaterDistorterEffect(m_xPFXEffectData.m_bWaterDistorterEffect);
		if(m_xPFXEffectData.m_bUsesSpline)
		{
			pxEffect->SetSpline(m_xPFXEffectData.m_pxSpline);
		}

		if (pxEffectTemplate)
		{
			// We must have a start time we want to use to set the age
			if(m_fStartTime > 0.0f)
			{
				const float fLifetime = pxEffectTemplate->m_fLifeTime;
				if(IsRandomRetrigger())
				{
					m_fStartTime = Asura_Random::GetFloat(0.f, fLifetime);
				}
				Asura_Assert(m_fStartTime < fLifetime, "Start time out of range for effect");
				// Age is in the range [0-1].
				pxEffect->SetAge(m_fStartTime / pxEffectTemplate->m_fLifeTime);
			}
		}
	}
}

void Asura_ClientEntity_PFX_Effect::StopEffect(bool bImmediate /* = false */)
{
	m_fTriggerTimer = 0.0f;
	SetEntityActive(false);

	if (m_iEffectID != ASURA_PFX_INVALID_EFFECT_ID)
	{
		// check if effect still active
		Asura_PFX_Entity_Effect* pxEffect = GetCurrentEffect();
		if (pxEffect)
		{
			pxEffect->Stop(bImmediate);
			if(bImmediate)
			{
				m_iEffectID = ASURA_PFX_INVALID_EFFECT_ID;
			}
		}
		else
		{
			//effect no longer exists , so we can chuck the ID away
			m_iEffectID = ASURA_PFX_INVALID_EFFECT_ID;
		}
	}
}

void Asura_ClientEntity_PFX_Effect::SetPositionAndOrientation(const Asura_Vector_3& xPosition,const Asura_Matrix_3x3& xOrient,bool bTeleport)
{
	m_xCurrentPosition = xPosition;
	m_xCurrentOrientation = xOrient;

	Asura_PFX_Entity_Effect* pxEffect = (Asura_PFX_Entity_Effect*)Asura_PFX_System::GetEffect(m_iEffectID);
	if(pxEffect)
	{
		pxEffect->SetPosition(xPosition,xOrient,bTeleport);
		
	}
}

void Asura_ClientEntity_PFX_Effect::Activate(bool bActive)
{
	if(bActive)
	{
		const Asura_PFX_Entity_Effect* pxEffect = GetCurrentEffect();
		if(!pxEffect || !pxEffect->IsRunning())
		{
			StartEffect();
		}
		SetEntityActive(true);
		if(IsRandomRetrigger() && !IsUpdateable())
		{
			AddToUpdateableClientList(this);
		}
	}
	else
	{
		const Asura_PFX_Entity_Effect* pxEffect = GetCurrentEffect();
		if(pxEffect && pxEffect->IsRunning())
		{
			StopEffect(false);
		}
		SetEntityActive(false);
	}
}

#ifdef ASURA_TOOLS
void Asura_ClientEntity_PFX_Effect::UpdateEffectProperties()
{
	//See if there is an active effect
	if (m_iEffectID != ASURA_PFX_INVALID_EFFECT_ID)
	{
		Asura_PFX_Entity_Effect* pxEffect = (Asura_PFX_Entity_Effect*)Asura_PFX_System::GetEffect(m_iEffectID);
		if(pxEffect)
		{
			//update it
			pxEffect->SetPosition(m_xCurrentPosition, m_xCurrentOrientation);
			pxEffect->SetCollisionPlane(m_xPFXEffectData.m_xCollisionPosition, m_xPFXEffectData.m_xCollisionDirection);
		}
	}
}

void Asura_ClientEntity_PFX_Effect::UpdateNumberOfSources(int iNumberOfSources)
{
	if (m_iEffectID != ASURA_PFX_INVALID_EFFECT_ID)
	{
		Asura_PFX_Entity_Effect* pxEffect = (Asura_PFX_Entity_Effect*)Asura_PFX_System::GetEffect(m_iEffectID);
		if(pxEffect)
		{
			//update it
			pxEffect->UpdateNumberOfSources(iNumberOfSources);
		}
	}	
}

void Asura_ClientEntity_PFX_Effect::UpdateMaximumParticles(int iSourceNumber, int iMaximumParticles)
{
	if (m_iEffectID != ASURA_PFX_INVALID_EFFECT_ID)
	{
		Asura_PFX_Entity_Effect* pxEffect = (Asura_PFX_Entity_Effect*)Asura_PFX_System::GetEffect(m_iEffectID);
		if(pxEffect)
		{
			//update it
			pxEffect->UpdateMaximumParticles(iSourceNumber, iMaximumParticles);
		}
	}	
}

void Asura_ClientEntity_PFX_Effect::ApplyChangesForTemplateInstance(Tools_EntityTemplateInstance* pxInstance)
{	
	m_xCurrentPosition = pxInstance->TransformPosition(m_xCurrentPosition);
	m_xCurrentOrientation = pxInstance->TransformMatrix(m_xCurrentOrientation);

	m_xPFXEffectData.ApplyChangesForTemplateInstance(pxInstance);
}

void Asura_ClientEntity_PFX_Effect::RenderVisibility()
{
	if (m_iEffectID != ASURA_PFX_INVALID_EFFECT_ID)
	{
		Asura_PFX_Effect* pxEffect = Asura_PFX_System::GetEffect(m_iEffectID);
		if(pxEffect)
		{
			pxEffect->RenderVisibility();
		}
	}	
}

Asura_Hash_ID Asura_ClientEntity_PFX_Effect::GetCurrentActiveTemplateHash() const
{
	if (m_iEffectID != ASURA_PFX_INVALID_EFFECT_ID)
	{
		Asura_PFX_Entity_Effect* pxEffect = (Asura_PFX_Entity_Effect*)Asura_PFX_System::GetEffect(m_iEffectID);
		if(pxEffect)
		{
			return pxEffect->GetCurrentTemplateHash();
		}
	}	
	return ASURA_HASH_ID_UNSET;
}

bool Asura_ClientEntity_PFX_Effect::IsEffectRunning() const
{
	if (m_iEffectID != ASURA_PFX_INVALID_EFFECT_ID)
	{
		Asura_PFX_Entity_Effect* pxEffect = (Asura_PFX_Entity_Effect*)Asura_PFX_System::GetEffect(m_iEffectID);
		if(pxEffect && pxEffect->IsRunning())
		{
			return true;
		}
	}	
	return false;
}


void Asura_ClientEntity_PFX_Effect::SetUseEffectSpecificRNG(bool bUse)
{
	m_bUseEffectSpecificRNG = bUse;
	//seed RNG based on guid so it will be consistent between recordings.
	if(bUse) m_xEffectSpecificRNG.SetSeed(GetGuid());
}

void Asura_ClientEntity_PFX_Effect::SetSelectedInTools(bool bSet)
{
	if(m_bSelectedInTools != bSet)
	{
		m_bSelectedInTools = bSet;
		Asura_PFX_Effect* pxEffect = (Asura_PFX_Effect*)Asura_PFX_System::GetEffect(m_iEffectID);
		if(pxEffect) pxEffect->SetSelectedInTools(bSet);

	}
}

#endif // ASURA_TOOLS


void Asura_ClientEntity_PFX_Effect::SetIgnoreModuleLinking(bool bIgnore)
{
	m_xPFXEffectData.m_bIgnoreModuleLinking = bIgnore;
	
	//update existing effect if there is one
	if (m_iEffectID != ASURA_PFX_INVALID_EFFECT_ID)
	{
		Asura_PFX_Entity_Effect* pxEffect = (Asura_PFX_Entity_Effect*)Asura_PFX_System::GetEffect(m_iEffectID);
		if(pxEffect) pxEffect->SetIgnoreModuleLinking(bIgnore);
	}

}

void Asura_ClientEntity_PFX_Effect::SetSkyboxEffect(bool bSkybox)
{
	m_xPFXEffectData.m_bSkyboxEffect = bSkybox;
	
	//update existing effect if there is one
	if (m_iEffectID != ASURA_PFX_INVALID_EFFECT_ID)
	{
		Asura_PFX_Entity_Effect* pxEffect = (Asura_PFX_Entity_Effect*)Asura_PFX_System::GetEffect(m_iEffectID);
		if(pxEffect) pxEffect->SetSkyboxEffect(bSkybox);
	}

}

void Asura_ClientEntity_PFX_Effect::SetWaterDistorterEffect(bool bWaterDistorter)
{
	m_xPFXEffectData.m_bWaterDistorterEffect = bWaterDistorter;

	//update existing effect if there is one
	if (m_iEffectID != ASURA_PFX_INVALID_EFFECT_ID)
	{
		Asura_PFX_Entity_Effect* pxEffect = (Asura_PFX_Entity_Effect*)Asura_PFX_System::GetEffect(m_iEffectID);
		if(pxEffect) pxEffect->SetWaterDistorterEffect(bWaterDistorter);
	}

}

void Asura_ClientEntity_PFX_Effect::CreateFromChunkStream(Asura_Guid uGuid, Asura_Chunk_Stream& xStream)
{
	Asura_Entity_System::SetNextClientGuid(uGuid);
	Asura_ClientEntity_PFX_Effect* pxNewEffect = new Asura_ClientEntity_PFX_Effect();
	pxNewEffect->ReadFromChunkStream(xStream);
}

Asura_PFX_Entity_Effect* Asura_ClientEntity_PFX_Effect::GetCurrentEffect() const
{
	return Asura_PFX_System::GetEntityEffect(m_iEffectID);
}



/// End of file. ///
