//////////////////////////////////////////////////////////////////////////////
//
// AVP_ClientActor_Weapon.cpp
//
// Copyright (c) 2007 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

#include "Core/Asura.h"

// This file's header.
#include "Entity/PhysicalObject/Actor/Weapons/AVP_ClientActor_Weapon.h"

// Engine independent.
#include "Animation/Asura_Animation.h"
#include "Animation/Asura_AnimationAttachment.h"
#include "Core/Asura_Timers.h"
#include "Entity/Asura_PosAndOriInterpolator.h"
#include "Entity/Ragdoll/Asura_ClientEntity_Ragdoll.h"
#include "Interface/Asura_CommandConsole.h"
#include "Network/Asura_Message.h"
#include "Network/Asura_Network.h"
#include "Network/Asura_Player.h"
#include "Physics/Asura_Physics.h"
#include "Rendering/Asura_Render.h"
#include "Shapes/Asura_Shapes.h"
#include "SpecialFX/PFX/Asura_PFX_System.h"
#include "SpecialFX/PFX/Asura_PFX_Entity_Effect.h"
#include "Core/AVP_Game_Core.h"

// Project independent.
#include "Actor/AVP_Actor_AnimationHandler.h"
#include "Actor/AVP_Actor_CameraHandler.h"
#include "Actor/AVP_Actor_HUDHandler.h"
#include "Actor/AVP_Actor_InputHandler.h"

#include "Actor/Vertebrates/Human/AVP_Human_Description.h"
#include "Animation/AVP_AnimFlags.h"
#include "Core/AVP_Settings.h"
#include "Entity/Triggers/AVP_ClientEntity_InteractionTrigger.h"
#include "Entity/AVP_Entity_Classification.h"
#include "Entity/AVP_Messages.h"
#include "Entity/PhysicalObject/Actor/AVP_Actor_Messages.h"
#include "Inventory/AVP_Inventory_System.h"
#include "Moves/AVP_Movement_System.h"
#include "Moves/AVP_Moves.h"

Asura_Hashed_List<AVP_ClientActor_Weapon> AVP_ClientActor_Weapon::s_xList;

AVP_ClientActor_Weapon::AVP_ClientActor_Weapon(const u_short usFlagsToIgnore)
: PARENT(usFlagsToIgnore)
{
	Classification = AVP_ENTITYCLASS_WEAPON;

	s_xList.AddToList( this );
}

AVP_ClientActor_Weapon::~AVP_ClientActor_Weapon( void ) 
{
	s_xList.RemoveFromList(this);
}

bool AVP_ClientActor_Weapon::HandleMessage( const Asura_Message* pxMessage )
{
	switch ( pxMessage->GetMsgID() )
	{
		case ASURA_MSG_CLIENTUPDATE:
		{
			const AVP_Message_Actor_ClientUpdate* pxData = static_cast< const AVP_Message_Actor_ClientUpdate* >( pxMessage->GetData() );

			// If we are inactive and now receiving a client update this means we are becoming active.
			// We should go visible and teleport to this first pos/ori so we don't zip across the level.
			if(!IsEntityActive())
			{
				Asura_Matrix_3x3 xOrientMatrix;
				pxData->m_xOrientation.ToMatrix( xOrientMatrix );
				TeleportTo( pxData->m_xPosition, xOrientMatrix );
			}

			ProcessClientUpdate( pxData, pxMessage->GetSentTime() );
			return true;
		}

		case ASURA_MSG_AXON_GS2_ANIM_SEQUENCE_DATA:
		{
			const Axon_Gamescene_AnimSequenceData* pxData = static_cast< const Axon_Gamescene_AnimSequenceData* >( pxMessage->GetData() );
			if ( m_pxAnimationHandler ) { m_pxAnimationHandler->HandleGamesceneAnimSequenceData( *pxData ); }
			return true;
		}

		case AVP_MSGID_REQUEST_ANIMATION:
		{
			const AVP_Message_Actor_RequestAnimation* pxData = static_cast< const AVP_Message_Actor_RequestAnimation* >( pxMessage->GetData() );
			if ( m_pxAnimationHandler ) { m_pxAnimationHandler->HandleAnimationRequest( *pxData ); }
			return true;
		}

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

void AVP_ClientActor_Weapon::ProcessClientUpdate(const AVP_Message_Actor_ClientUpdate* pxData, float fServerTime, bool bProcessPosAndOri /*= true*/)
{
#ifndef ASURA_NO_NETWORK_LAG_COMPENSATION
	const bool bAllowPosAndOrientationProcessing = bProcessPosAndOri && (m_pxPosAndOriInterpolator != NULL);
#else // #ifndef ASURA_NO_NETWORK_LAG_COMPENSATION
	const bool bAllowPosAndOrientationProcessing = bProcessPosAndOri;
#endif // #ifndef ASURA_NO_NETWORK_LAG_COMPENSATION

	// Call the base-class...
	PARENT::ProcessClientUpdate(pxData, fServerTime, bAllowPosAndOrientationProcessing);
}

void AVP_ClientActor_Weapon::GetAimDirection( Asura_AVector3& xAimDir ) const
{
	m_xAimDirInterpolator.GetCurrent( xAimDir );
}

void AVP_ClientActor_Weapon::SetAimDirection( const Asura_AVector3& xAimDir, const float fServerTime /*= -1.0f */ )
{
	m_xAimDirInterpolator.Update( xAimDir, fServerTime );
}

void AVP_ClientActor_Weapon::PostCreateInitialise()
{
	const Asura_Matrix_3x3& xOri = GetCurrentOrientation();
	m_xAimDirInterpolator.Reset( Asura_AVector3( xOri.e13, xOri.e23, xOri.e33 ) );
}

/// End of file. ///
