/**
*
* \file Asura_ClientEntity_AdvancedLight.cpp
*
* Created by Richard May - 07/01/2003 10:53:15
*
* Copyright (C) 2002 Rebellion, All Rights Reserved.
*
* \brief
*
**/



/************/
/* Includes.*/
/************/

// main asura header
#include "Core/Asura.h"

#ifndef ASURA_TARGET_SM3

// local header
#include "Entity/PhysicalObject/Asura_ClientEntity_AdvancedLight.h"

// asura
#include "Entity/Asura_Entity_Classification.h"
#include "Entity/PhysicalObject/Asura_ServerEntity_AdvancedLight.h"
#include "Core/Asura_Timers.h"
#include "Light/Asura_Photon.h"
#include "Network/Asura_Message.h"
#include "SpecialFX/Asura_Corona_System.h"

// C O N S T A N T S /////////////////////////////////////////////////////////

#if ASURA_CLIENTENTITY_ADVANCEDLIGHT_DO_VIS_CHECKS
static const u_int MAX_FRAMES_BETWEEN_VIS_CHECKS = 8; // Must be a power of two.
#endif

// G L O B A L S /////////////////////////////////////////////////////////////

#if ASURA_CLIENTENTITY_ADVANCEDLIGHT_DO_VIS_CHECKS
static u_int  g_uVisCheckOffsetForNextLight = 0;
static short* g_psOutputIntersectingModuleList;
static u_int  g_uNumIntersectingModules;
#endif

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

/**************/
/* Functions. */
/**************/

/*** Constructor ***/
Asura_ClientEntity_AdvancedLight::Asura_ClientEntity_AdvancedLight() : Asura_ClientEntity_DestructibleLight()
{
	Classification = AsuraEntityClass_AdvancedLight;
	m_uCutsceneControlled = false;

	m_fStrobeTimer = 0.0f;
	m_fCurrentStrobeDuration = m_fMaxTimeOn = 0.0f;
	
	m_fFadeTimer = 0.0f;
	m_fCurrentFadeDuration = m_fMaxStartColourTime  = 0.0f;
	m_eColourFadePhase = FADE_PHASE_ATSTART;

	m_fRadiusTimer = 0.0f;
	m_fCurrentRadiusDuration = m_fMaxStartRadiusTime = 0.0f;
	m_eRadiusPhase = FADE_PHASE_ATSTART;

#if ASURA_CLIENTENTITY_ADVANCEDLIGHT_DO_VIS_CHECKS
    RefreshIntersectingModuleList();
#endif
	s_xList.AddToList(this);
}


/*** Destructor ***/
Asura_ClientEntity_AdvancedLight::~Asura_ClientEntity_AdvancedLight()
{
	s_xList.RemoveFromList(this);
}


/*************************************************************
 *
 * Name          : Asura_ClientEntity_AdvancedLight::HandleMessage
 *
 * Author        : Richard May
 *
 * Description   : Message handler
 *
 *************************************************************/
bool Asura_ClientEntity_AdvancedLight::HandleMessage(const Asura_Message* pxMessage)
{
	// check message pointer
	if(!pxMessage) return false;
	
	// Process a message from the server
	switch(pxMessage->GetMsgID())
	{
		case ASURA_MSG_CLIENTUPDATE :
		{
			const Asura_Message_AdvancedLight_ClientUpdate* pxData = 
				static_cast<const Asura_Message_AdvancedLight_ClientUpdate*> (pxMessage->GetData());
			
			Asura_Assert( pxData, "Couldn't access message data!" );			
			if(!pxData) return true;

#if ASURA_CLIENTENTITY_ADVANCEDLIGHT_DO_VIS_CHECKS
            bool bNeedRefresh = ( pxData->m_fRange > m_pxPhoton->GetRange() || !pxData->m_xPosition.ApproximatelyEquals(m_pxPhoton->GetPosition()) );
#endif

			// process static object update
			if(!m_uCutsceneControlled)
			{
				ProcessClientUpdate(pxData, pxMessage->GetSentTime());
			}
	
			if (m_pxPhoton)
            {
				if( m_eRadiusPhase == FADE_PHASE_NONE )
				{
					m_pxPhoton->SetRange(pxData->m_fRange);
				}
				
				if( m_eColourFadePhase == FADE_PHASE_NONE )
				{
					float fScale = (pxData->m_fBrightness / 255.0f) / 2.0f;
					SetPhotonAndCoronaColour( pxData->m_fR * fScale, pxData->m_fG * fScale, pxData->m_fB * fScale);
				}
            }	
			
			if(!m_uCutsceneControlled)
			{
				m_uActive = pxData->m_bActive;
			}

#if ASURA_CLIENTENTITY_ADVANCEDLIGHT_DO_VIS_CHECKS
            if( bNeedRefresh ) { RefreshIntersectingModuleList(); }
#endif

			return true;
		}

		case ASURA_MSG_CLIENTCREATE :
		{
			Asura_Assert(pxMessage->GetEntityClassification() == Classification, "Create message sent to wrong entity type.");

			/// Richard May - 16/01/2003 16:32:41 - we've received a creation message and we already exist.
			/// In this case, we want to reinitialise the values of the advancedlight as handlemessage
			/// is called subsequent to the project create being called (and creation messages may be sent
			/// after the actual server object's creation due to changes made in tools, etc)

			const Asura_Message_AdvancedLight_Create* pxData = 
				static_cast<const Asura_Message_AdvancedLight_Create*> (pxMessage->GetData());
			
			Asura_Assert( pxData, "Couldn't access message data!" );			
			if(!pxData) return true;	

			ProcessClientUpdate(pxData, pxMessage->GetSentTime());

			// flicker & strobe
			m_fMinTimeOff = pxData->m_fMinTimeOff;
			m_fMaxTimeOff = pxData->m_fMaxTimeOff;
			m_fMinTimeOn = pxData->m_fMinTimeOn;
			m_fMaxTimeOn = pxData->m_fMaxTimeOn;
			
			float fScale = (pxData->m_fBrightness / 255.0f) / 2.0f;

			// colour fade 
			m_fEndColourR = pxData->m_fEndColourR * fScale;
			m_fEndColourG = pxData->m_fEndColourG * fScale;
			m_fEndColourB = pxData->m_fEndColourB * fScale;
			
			m_fStartColourR = pxData->m_fStartColourR * fScale;
			m_fStartColourG = pxData->m_fStartColourG * fScale;
			m_fStartColourB = pxData->m_fStartColourB * fScale;
			
			m_fMaxFadeDownDuration = pxData->m_fMaxFadeDownDuration;
			m_fMinFadeDownDuration = pxData->m_fMinFadeDownDuration;
			m_fMaxFadeUpDuration = pxData->m_fMaxFadeUpDuration;
			m_fMinFadeUpDuration = pxData->m_fMinFadeUpDuration;
			
			m_fMinStartColourTime = pxData->m_fMinStartColourTime;
			m_fMaxStartColourTime = pxData->m_fMaxStartColourTime;
			m_fMinEndColourTime = pxData->m_fMinEndColourTime;
			m_fMaxEndColourTime = pxData->m_fMaxEndColourTime;
			
			// radius change
			m_fEndRadius = pxData->m_fEndRadius;
			m_fStartRadius = pxData->m_fStartRadius;
			
			m_fMaxRadiusDownDuration = pxData->m_fMaxRadiusDownDuration;
			m_fMinRadiusDownDuration = pxData->m_fMinRadiusDownDuration;
			m_fMaxRadiusUpDuration = pxData->m_fMaxRadiusUpDuration;
			m_fMinRadiusUpDuration = pxData->m_fMinRadiusUpDuration;
			
			m_fMinStartRadiusTime = pxData->m_fMinStartRadiusTime;
			m_fMaxStartRadiusTime = pxData->m_fMaxStartRadiusTime;
			m_fMinEndRadiusTime = pxData->m_fMinEndRadiusTime;
			m_fMaxEndRadiusTime = pxData->m_fMaxEndRadiusTime;
			
			// attached entity
			m_uMasterEntity = pxData->m_uMasterEntity;
			m_xOffsetFromMaster = pxData->m_xOffsetFromMaster;
			m_uMasterMarker = pxData->m_uMasterMarker;
			m_uUseMasterOrient = pxData->m_uUseMasterOrient;
			
			// control flags
			m_uActive = pxData->m_uActive;
			m_uLoopFade = pxData->m_uLoopFade;
			m_uLoopRadius = pxData->m_uLoopRadius;
			
            if (!m_pxPhoton)
            {
                m_pxPhoton = Asura_Photon_System::CreatePhoton();
			}

			if (m_pxPhoton)
			{
				m_pxPhoton->SetPosition( pxData->m_xPosition );
				m_pxPhoton->SetRange( pxData->m_fRange );
				float fScale = (pxData->m_fBrightness / 255.0f) / 2.0f;
                m_pxPhoton->SetColours( pxData->m_fR * fScale, pxData->m_fG * fScale, pxData->m_fB * fScale);
				m_pxPhoton->SetUseBoundingBox( pxData->m_bUseBoundingBox);
				m_pxPhoton->SetBoundingBox( pxData->m_xBoundingBox );
				m_pxPhoton->SetAsActive( m_uActive );
				m_pxPhoton->SetDontLightEnv(pxData->m_bDontLightEnv);

			}

			UpdateCorona(pxData);
			
#if ASURA_CLIENTENTITY_ADVANCEDLIGHT_DO_VIS_CHECKS
            RefreshIntersectingModuleList();
#endif

			return true;
		}

		default : break;			
	}

	return false;
}
/* end of function HandleMessage */


/*************************************************************
 *
 * Name          : Asura_ClientEntity_AdvancedLight::Update
 *
 * Author        : Richard May
 *
 * Description   : Main update function
 *
 *************************************************************/
void Asura_ClientEntity_AdvancedLight::Update ( void )
{
#if ASURA_CLIENTENTITY_ADVANCEDLIGHT_DO_VIS_CHECKS
    if( m_uCanDoVisChecks )
    {
        if( m_uFramesSinceVisCheck >= MAX_FRAMES_BETWEEN_VIS_CHECKS )
        {
            m_uVisible = false;
            for( u_int u = 0; m_asIntersectingModules[u] >= 0 && u < MAX_INTERSECTING_MODULES; ++u )
            {
                if( Asura_Module_System::IsModuleVisible(m_asIntersectingModules[u], 0xFFFFFFFFu) )
                {
                    m_uVisible = true;
                    break;
                }
            }

            m_uFramesSinceVisCheck = 0;
        }
        
        ++m_uFramesSinceVisCheck;

        if( !m_uVisible ) { return; }
    }
#endif

	if (IsDead() ||
		IsDestroyed()) return;

	Asura_Assert( m_pxPhoton, "ERROR - Photon pointer is invalid!" );
	if(!m_pxPhoton) return;

	float fTimeSlice = Asura_Timers::GetGameTimeSlice();
	
	if(m_uActive)    
	{
		if( !m_pxPhoton->IsActive() && (m_fCurrentStrobeDuration == -1.0f) )
		{
			SetPhotonAndCoronaActive(true);
		}

		// update strobe/flicker
		{
			m_fStrobeTimer += fTimeSlice;

			// check whether a phase (on/off) change is required
			if( (m_fStrobeTimer > m_fCurrentStrobeDuration) && (m_fCurrentStrobeDuration != -1.0f) )	 
			{
				// check the current status of the photon
				if( m_pxPhoton->IsActive() )
				{
					// if the photon is currently on, switch to an inactive (off) phase & set a new random duration
					m_fCurrentStrobeDuration = Asura_Random::GetFloat( m_fMinTimeOff, m_fMaxTimeOff );
					SetPhotonAndCoronaActive(false);
				}
				else
				{
					m_fCurrentStrobeDuration = Asura_Random::GetFloat( m_fMinTimeOn, m_fMaxTimeOn );
					SetPhotonAndCoronaActive(true);

				}
				m_fStrobeTimer = 0.0f;
			}	

			if(m_fCurrentStrobeDuration == -1.0f)
			{
				SetPhotonAndCoronaActive(true);
			}
		}

		// update colour fade
		if( (m_fMinStartColourTime == -1.0f) && (m_fMaxStartColourTime == -1.0f) && 
			(m_fMinEndColourTime == -1.0f) && (m_fMaxEndColourTime == -1.0f) )
		{
			m_eColourFadePhase = FADE_PHASE_NONE;
		}
		else
		{
			if(m_eColourFadePhase == FADE_PHASE_NONE)
			{
				m_eColourFadePhase = FADE_PHASE_ATSTART;
			}

			m_fFadeTimer += fTimeSlice;

			// if we're currently fading, set the current colour of the photon
			if( (m_eColourFadePhase == FADE_PHASE_DOWN) && (m_fCurrentFadeDuration > 0.0f) )
			{
				float fFadePercent = (m_fFadeTimer / m_fCurrentFadeDuration);
				if(fFadePercent > 1.0f) fFadePercent = 1.0f;
				float fRed = m_fStartColourR + ((m_fEndColourR - m_fStartColourR) * fFadePercent);
				float fGreen = m_fStartColourG + ((m_fEndColourG - m_fStartColourG) * fFadePercent);
				float fBlue = m_fStartColourB + ((m_fEndColourB - m_fStartColourB) * fFadePercent);

				SetPhotonAndCoronaColour( fRed, fGreen, fBlue);
			}
			else if( (m_eColourFadePhase == FADE_PHASE_UP) && (m_fCurrentFadeDuration > 0.0f) )
			{
				float fFadePercent = (m_fFadeTimer / m_fCurrentFadeDuration);
				if(fFadePercent > 1.0f) fFadePercent = 1.0f;
				float fRed = m_fEndColourR + ((m_fStartColourR - m_fEndColourR) * fFadePercent);
				float fGreen = m_fEndColourG + ((m_fStartColourG - m_fEndColourG) * fFadePercent);
				float fBlue = m_fEndColourB + ((m_fStartColourB - m_fEndColourB) * fFadePercent);

				SetPhotonAndCoronaColour( fRed, fGreen, fBlue);
			}

			// check for phase end/switch
			if( (m_fFadeTimer > m_fCurrentFadeDuration) && (m_fCurrentFadeDuration != -1.0f) )
			{
				switch(m_eColourFadePhase)
				{
					case FADE_PHASE_UP : 
					{	
						m_eColourFadePhase = FADE_PHASE_ATSTART;  
						m_fCurrentFadeDuration = Asura_Random::GetFloat( m_fMinStartColourTime, m_fMaxStartColourTime );
						break;
					}

					case FADE_PHASE_DOWN : 
					{
						m_eColourFadePhase = FADE_PHASE_ATEND; 
						m_fCurrentFadeDuration = Asura_Random::GetFloat( m_fMinEndColourTime, m_fMaxEndColourTime );
						break;
					}

					case FADE_PHASE_ATSTART : 
					{
						m_eColourFadePhase = FADE_PHASE_DOWN;  
						m_fCurrentFadeDuration = Asura_Random::GetFloat( m_fMinFadeDownDuration, m_fMaxFadeDownDuration );
						break;
					}

					case FADE_PHASE_ATEND : 
					{
						if(m_uLoopFade)
						{
							m_eColourFadePhase = FADE_PHASE_UP; 
							m_fCurrentFadeDuration = Asura_Random::GetFloat( m_fMinFadeUpDuration, m_fMaxFadeUpDuration );						
						}
						break;
					}

					default : break;// do nothing 
				}

				m_fFadeTimer = 0.0f;
			}
		}

		// update radius fade
		if( (m_fMinStartRadiusTime == -1.0f) && (m_fMaxStartRadiusTime == -1.0f) && 
			(m_fMinEndRadiusTime == -1.0f) && (m_fMaxEndRadiusTime == -1.0f) )
		{
			m_eRadiusPhase = FADE_PHASE_NONE;
		}
		else
		{
			if(m_eRadiusPhase == FADE_PHASE_NONE)
			{
				m_eRadiusPhase = FADE_PHASE_ATSTART;
			}

			m_fRadiusTimer += fTimeSlice;
			
			// if we're currently fading, set the current colour of the photon
			if( (m_eRadiusPhase == FADE_PHASE_DOWN) && (m_fCurrentRadiusDuration > 0.0f) )
			{
				float fFadePercent = (m_fRadiusTimer / m_fCurrentRadiusDuration);
				if(fFadePercent > 1.0f) fFadePercent = 1.0f;
				m_pxPhoton->SetRange( m_fStartRadius + ((m_fEndRadius - m_fStartRadius) * fFadePercent) );
			}
			else if( (m_eRadiusPhase == FADE_PHASE_UP) && (m_fCurrentRadiusDuration > 0.0f) )
			{
				float fFadePercent = (m_fRadiusTimer / m_fCurrentRadiusDuration);
				if(fFadePercent > 1.0f) fFadePercent = 1.0f;
				m_pxPhoton->SetRange( m_fEndRadius + ((m_fStartRadius - m_fEndRadius) * fFadePercent) );
			}
			
			// check for phase end/switch
			if( (m_fRadiusTimer > m_fCurrentRadiusDuration) && (m_fCurrentRadiusDuration != -1.0f) )
			{
				switch(m_eRadiusPhase)
				{
				case FADE_PHASE_UP : 
					{	
						m_eRadiusPhase = FADE_PHASE_ATSTART;  
						m_fCurrentRadiusDuration = Asura_Random::GetFloat( m_fMinStartRadiusTime, m_fMaxStartRadiusTime );
						break;
					}
					
				case FADE_PHASE_DOWN : 
					{
						m_eRadiusPhase = FADE_PHASE_ATEND; 
						m_fCurrentRadiusDuration = Asura_Random::GetFloat( m_fMinEndRadiusTime, m_fMaxEndRadiusTime );
						break;
					}
					
				case FADE_PHASE_ATSTART : 
					{
						m_eRadiusPhase = FADE_PHASE_DOWN;  
						m_fCurrentRadiusDuration = Asura_Random::GetFloat( m_fMinRadiusDownDuration, m_fMaxRadiusDownDuration );
						break;
					}
					
				case FADE_PHASE_ATEND : 
					{
						if(m_uLoopRadius)
						{
							m_eRadiusPhase = FADE_PHASE_UP; 
							m_fCurrentRadiusDuration = Asura_Random::GetFloat( m_fMinRadiusUpDuration, m_fMaxRadiusUpDuration );						
						}
						break;
					}
					
				default : break;// do nothing 
				}
				
				m_fRadiusTimer = 0.0f;
			}
		}

	}
	else
	{
		// deactivate photon
		SetPhotonAndCoronaActive(false);
	}	


	// update position of entity based on master
	if(m_uMasterEntity != ASURA_GUID_UNREGISTERED)
	{
		Asura_ClientEntity_PhysicalObject* pxMaster = Asura_ClientEntity_PhysicalObject::FindEntity(m_uMasterEntity);
		if(pxMaster)
		{
			const Asura_Vector_3&	xCurrentPosition	= GetCurrentPosition();
			Asura_Vector_3 xPosition = xCurrentPosition;
			Asura_Matrix_3x3 xOrientation = GetCurrentOrientation();
			if(m_uMasterMarker)
			{
				pxMaster->GetMarkerLocationFromHash(m_uMasterMarker,&xPosition,m_uUseMasterOrient ? &xOrientation : NULL);
			}
			else
			{
				xPosition = m_xOffsetFromMaster;
				if(m_uUseMasterOrient)
				{
					xPosition = xPosition * pxMaster->GetCurrentOrientation();
					xPosition = pxMaster->GetCurrentPosition() + xPosition;
					xOrientation = pxMaster->GetCurrentOrientation();
				}
				else
				{
					xPosition = pxMaster->GetCurrentPosition() + m_xOffsetFromMaster;
				}
			}

			
//#ifndef ASURA_NO_NETWORK_LAG_COMPENSATION
//			m_xLastReportedPosition = xPosition;	
//			m_xPrevReportedPosition = xPosition;
//#endif // ASURA_NO_NETWORK_LAG_COMPENSATION
//
//			m_xCurrentPosition = xPosition;
//			m_xCurrentOrientation = xOrientation;			
//
//#ifndef ASURA_NO_NETWORK_LAG_COMPENSATION
//			m_xLastReportedOrientation.FromMatrix(xOrientation);
//			m_xPrevReportedOrientation.FromMatrix(xOrientation);
//#endif // ASURA_NO_NETWORK_LAG_COMPENSATION
			TeleportTo(xPosition, xOrientation);
			GetShapeInstance().SetNewPosAndOri(xPosition, xOrientation);

			if(m_iCoronaHandle != ASURA_INVALID_HANDLE)
			{
				Asura_Corona_System::SetPosition(m_iCoronaHandle, xPosition);
			}
		}
	}

	m_pxPhoton->SetPosition(m_xCurrentPosition);
}
/* end of function Update */


void Asura_ClientEntity_AdvancedLight::SetPhotonAndCoronaActive(bool bActive)
{
	if(m_pxPhoton)
	{
		m_pxPhoton->SetAsActive(bActive);
	}
	if(m_iCoronaHandle != ASURA_INVALID_HANDLE)
	{
		Asura_Corona_System::SetFlag_Hidden(m_iCoronaHandle,!bActive);
	}
}



bool Asura_ClientEntity_AdvancedLight::GetLightColour(float *afColour)
{
	if (!m_pxPhoton) return false;
	if (!m_pxPhoton->IsActive()) return false;
	afColour[0] = m_pxPhoton->GetRedComponent();
	afColour[1] = m_pxPhoton->GetGreenComponent();
	afColour[2] = m_pxPhoton->GetBlueComponent();
	return true;
}


void Asura_ClientEntity_AdvancedLight::Create(const Asura_Message* pxMessage)
{
	if (!pxMessage) { return; }

	Asura_Assert(pxMessage->GetMsgID() == ASURA_MSG_CLIENTCREATE, "Wrong message to create an advanced light with.");
    Asura_Assert(pxMessage->GetEntityClassification() == AsuraEntityClass_AdvancedLight, "Creating an advanced light with the wrong entity type.");

	Asura_ClientEntity_AdvancedLight* pxLight = new Asura_ClientEntity_AdvancedLight();
	if (pxLight)
	{
		pxLight->HandleMessage(pxMessage);
	}
}


#if ASURA_CLIENTENTITY_ADVANCEDLIGHT_DO_VIS_CHECKS

bool Asura_ClientEntity_AdvancedLight::IntersectingModuleListCallback( u_short uModuleIdx )
{
    Asura_Assert( uModuleIdx < 32768, "" ); // Since we're using signed shorts for module indices.

    if( g_uNumIntersectingModules < MAX_INTERSECTING_MODULES )
    {
        g_psOutputIntersectingModuleList[g_uNumIntersectingModules++] = uModuleIdx;
        return true;
    }
    else
    {
        g_uNumIntersectingModules = 0;
        return false;
    }
}

void Asura_ClientEntity_AdvancedLight::RefreshIntersectingModuleList( void )
{
    // (MP - 12.06.2003) For now, we'll skip visibility checks for advanced
    // lights that are attached to an entity, the assumption being that the
    // purpose of this will be to move the light with the entity, meaning we
    // end up doing lots of recalculations of the intersecting module list.
    // TODO: It would probably be sufficient to assume that the attached light
    // is visible iff the master entity is. Unfortunately this information
    // isn't currently available in the renderable or physical object client
    // entity interfaces.

    m_uCanDoVisChecks = false;

    if( m_pxPhoton && ASURA_GUID_UNREGISTERED == m_uMasterEntity )
    {
        g_psOutputIntersectingModuleList = m_asIntersectingModules;
        g_uNumIntersectingModules        = 0;

        if( FADE_PHASE_NONE == m_eRadiusPhase )
        {
            Asura_Module_System::TestModuleTree( m_pxPhoton->GetBoundingBox(), IntersectingModuleListCallback );
        }
        else
        {
            Asura_Bounding_Box xBB;

            {
                const Asura_Vector_3& xPos = m_pxPhoton->GetPosition();

                float fRadius = Asura_Maths::Max( m_fStartRadius, m_fEndRadius );

                xBB.MinX = xPos.x - fRadius;
                xBB.MinY = xPos.y - fRadius;
                xBB.MinZ = xPos.z - fRadius;
                xBB.MaxX = xPos.x + fRadius;
                xBB.MaxY = xPos.y + fRadius;
                xBB.MaxZ = xPos.z + fRadius;
            }

            Asura_Module_System::TestModuleTree( xBB, IntersectingModuleListCallback );
        }

        if( g_uNumIntersectingModules )
        {
            m_uCanDoVisChecks      = true;
            m_uVisible             = true;
            m_uFramesSinceVisCheck = g_uVisCheckOffsetForNextLight;

            ++g_uVisCheckOffsetForNextLight &= (MAX_FRAMES_BETWEEN_VIS_CHECKS - 1);

            if( g_uNumIntersectingModules < MAX_INTERSECTING_MODULES )
            {
                m_asIntersectingModules[g_uNumIntersectingModules + 1] = -1;
            }
        }
    }
}

#endif // #if ASURA_CLIENTENTITY_ADVANCEDLIGHT_DO_VIS_CHECKS

void Asura_ClientEntity_AdvancedLight::ClientSideActivate(bool bActivate)
{
	m_uActive = bActivate ? 1 : 0;
	SetPhotonAndCoronaActive(bActivate);
}

void Asura_ClientEntity_AdvancedLight::SetPositionAndOrientation(const Asura_Vector_3& xPos, const Asura_Matrix_3x3& xMat)
{
	TeleportTo(xPos,xMat);
	GetShapeInstance().SetNewPosAndOri(xPos,xMat);
	if(m_pxPhoton)
	{
		m_pxPhoton->SetPosition(xPos);
	}

	if(m_iCoronaHandle != ASURA_INVALID_HANDLE)
	{
		Asura_Corona_System::SetPosition(m_iCoronaHandle,xPos);
	}
}

#endif // #ifndef ASURA_TARGET_SM3
