/*
	Free view camera script
	--------------------------------------------------
	A script to control the camera in free view mode.
	Could be useful for a spectate mode for example.
	
	Author: Juppi
*/

pCamera <- array(GetMaxPlayers()); // Camera class object

class CCamera
{
	/// -- These are the interface funcs for this class
	// CCamera::Enable() - Enables the free camera
	// CCamera::Disable() - Disables the free camera
	// CCamera::IsEnabled() - Returns whether the camera has been enabled/disabled
	// CCamera::Process() - Processes the camera each frame and updates the GTA camera position
	
	/// -- These are general camera movement functions. They don't do anything else than calculate and update the internal member vars
	// CCamera::Rotate( fHoriz, fVert ) - Rotates the camera horizontally/vertically
	// CCamera::Move( fDist ) - Moves the camera forward/backward
	// CCamera::MoveSideways( fDist ) - Moves the camera sideways
	

	function IsEnabled() { return bEnabled; }
	function Pos() { return vPos; }
	function Target() { return vTarget; }
	function _typeof() { return "CCamera"; }
	function Remove() { this.clear(); }
	
	// Camera position
	vPos = Vector( 0.0, 0.0, 0.0 );
	vTarget = Vector( 0.0, 0.0, 0.0 );
	fYaw = 0.0;
	fPitch = 0.0;
	fSpeed = 1.5;
	pPlayer = null;
	
	// Camera status
	bEnabled = false;
	bMovingForward = null;
	bMovingLeft = null;
	bMovingBackward = null;
	bMovingRight = null;
	bRotatingUp = null;
	bRotatingLeft = null;
	bRotatingDown = null;
	bRotatingRight = null;
}

function CCamera::Enable()
{
	// Set the initial place and rotation of the camera
	vPos = pPlayer.Pos;
	fPitch = 0.0;
	fYaw = 0.0;
	
	Rotate( -1 * pPlayer.Angle * PI/180.0, 0.0 );
	
	pPlayer.SetCameraPos( vPos, vTarget );
	pPlayer.Frozen = true;
	
	bEnabled = true;
}

function CCamera::Disable()
{
	pPlayer.Pos = vPos;

	pPlayer.Frozen = false;
	
	pPlayer.RestoreCamera();
	
	bEnabled = false;
}

function CCamera::Rotate( fHoriz, fVert )
{
	fYaw += fHoriz;
	fPitch += fVert;
	
	vTarget.x = vPos.x + cos( fPitch ) * sin( fYaw );
	vTarget.y = vPos.y + cos( fPitch ) * cos( fYaw );
	vTarget.z = vPos.z + sin( fPitch );
}

function CCamera::Move( fDist )
{
	vPos.x += fDist * cos( fPitch ) * sin( fYaw );
	vPos.y += fDist * cos( fPitch ) * cos( fYaw );
	vPos.z += fDist * sin( fPitch );
	
	Rotate( 0.0, 0.0 );
}

function CCamera::MoveSideways( fDist )
{
	vPos.x += fDist * cos( fPitch ) * sin( fYaw + PI/2 );
	vPos.y += fDist * cos( fPitch ) * cos( fYaw + PI/2 );
	
	Rotate( 0.0, 0.0 );
}

function CCamera::Process()
{
	local bMoving = false;
	local fCamSpeed = fSpeed;
	
	if ( bMovingForward )
	{
		Move( fCamSpeed );
		bMoving = true;
	}
	if ( bMovingBackward )
	{
		Move( -fCamSpeed );
		bMoving = true;
	}
	if ( bMovingLeft )
	{
		MoveSideways( -fCamSpeed );
		bMoving = true;
	}
	if ( bMovingRight )
	{
		MoveSideways( fCamSpeed );
		bMoving = true;
	}
	if ( bRotatingUp )
	{
		Rotate( 0.0, 0.1 );
		bMoving = true;
	}
	if ( bRotatingDown )
	{
		Rotate( 0.0, -0.1 );
		bMoving = true;
	}
	if ( bRotatingLeft )
	{
		Rotate( -0.1, 0.0 );
		bMoving = true;
	}
	if ( bRotatingRight )
	{
		Rotate( 0.1, 0.0 );
		bMoving = true;
	}
	
	if ( bMoving )
	{
		pPlayer.SetCameraPos( vPos, vTarget );
	}
}

function onCamScriptLoad()
{
	pUpdateTimer <- NewTimer("Update", 1000/30, 0);
	
	KEY_W <- BindKey(true, 0x57, 0, 0);
	KEY_A <- BindKey(true, 0x41, 0, 0);
	KEY_S <- BindKey(true, 0x53, 0, 0);
	KEY_D <- BindKey(true, 0x44, 0, 0);
	//ArrowUp <- BindKey(true, 0x26, 0, 0);
	//ArrowLeft <- BindKey(true, 0x25, 0, 0);
	//ArrowDown <- BindKey(true, 0x28, 0, 0);
	//ArrowRight <- BindKey(true, 0x27, 0, 0);
}

function Update()
{
	for (local i = 0; i < pCamera.len(); i++)
	{
		if (pCamera[i])
		{
			if (pCamera[i].IsEnabled())
				pCamera[i].Process();
		}
	}
}

function onCamPlayerJoin( pPlayer )
{
	pCamera[pPlayer.ID] = CCamera();
	pCamera[pPlayer.ID].pPlayer = FindPlayer(pPlayer.ID);
}

function onCamPlayerPart( pPlayer, ... )
{
	pCamera[pPlayer.ID] = null;
}

/*function onPlayerCommand( pPlayer, szCommand, szText )
{
	if ( szCommand == "cam" )
	{
		if ( !pCamera[pPlayer.ID].IsEnabled() )
		{
			pCamera[pPlayer.ID].Enable();
			pData[pPlayer.ID].Editing = false;
			MessagePlayer( "[#00CC00][CAM]: [#ffffff]Free view camera [#00CC00]enabled[#ffffff]. Type '/cam' to disable.", pPlayer );
		}
		else
		{
			pCamera[pPlayer.ID].Disable();
			MessagePlayer( "[#00CC00][CAM]: [#ffffff]Free view camera [#00CC00]disabled[#ffffff].", pPlayer );
		}
	}

	return 1;
}
*/

function onCamKeyDown( pPlayer, iKey )
{
	if (pCamera[pPlayer.ID].IsEnabled())
	{
		switch ( iKey )
		{
			case KEY_W:
				pCamera[pPlayer.ID].bMovingForward = true;
				break;
			case KEY_A:
				pCamera[pPlayer.ID].bMovingLeft = true;
				break;
			case KEY_S:
				pCamera[pPlayer.ID].bMovingBackward = true;
				break;
			case KEY_D:
				pCamera[pPlayer.ID].bMovingRight = true;
				break;
			case ArrowUp:
				pCamera[pPlayer.ID].bRotatingUp = true;
				break;
			case ArrowLeft:
				pCamera[pPlayer.ID].bRotatingLeft = true;
				break;
			case ArrowDown:
				pCamera[pPlayer.ID].bRotatingDown = true;
				break;
			case ArrowRight:
				pCamera[pPlayer.ID].bRotatingRight = true;
				break;
		}
	}
}

function onCamKeyUp( pPlayer, iKey )
{
	if (pCamera[pPlayer.ID].IsEnabled())
	{
		switch ( iKey )
		{
			case KEY_W:
				pCamera[pPlayer.ID].bMovingForward = false;
				break;
			case KEY_A:
				pCamera[pPlayer.ID].bMovingLeft = false;
				break;
			case KEY_S:
				pCamera[pPlayer.ID].bMovingBackward = false;
				break;
			case KEY_D:
				pCamera[pPlayer.ID].bMovingRight = false;
				break;
			case ArrowUp:
				pCamera[pPlayer.ID].bRotatingUp = false;
				break;
			case ArrowLeft:
				pCamera[pPlayer.ID].bRotatingLeft = false;
				break;
			case ArrowDown:
				pCamera[pPlayer.ID].bRotatingDown = false;
				break;
			case ArrowRight:
				pCamera[pPlayer.ID].bRotatingRight = false;
				break;
		}
	}
}