void UpdateAvatarEffect(void)
{
	if(!haptics->HasDevice())
		return;

	Vector vel;
	Vector vvel;
	Vector evel;
	QAngle eye;
	C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer();
	if(!pPlayer)
		return;

	eye = pPlayer->GetAbsAngles();

	if(pPlayer->IsInAVehicle() && pPlayer->GetVehicle())
	{
		pPlayer->GetVehicle()->GetVehicleEnt()->EstimateAbsVelocity(vvel);
		eye = pPlayer->GetVehicle()->GetVehicleEnt()->EyeAngles();

		if(!Q_stristr(pPlayer->GetVehicle()->GetVehicleEnt()->GetClassname(),"choreo"))
		{
			eye[YAW] += 90;
		}
		


	}
	else
	{
		vel = pPlayer->GetAbsVelocity();
	}

	Vector PlayerVel = pPlayer->GetAbsVelocity();

	//Choreo vehicles use player avatar and don't produce their own velocity
	if(!pPlayer->GetVehicle() || abs(vvel.Length()) == 0 )
	{
		vel = PlayerVel;
	}
	else
		vel = vvel;


	
	VectorYawRotate(vel, -90 -eye[YAW], vel );

	vel.y = -vel.y;
	vel.z = -vel.z;
	
	switch(pPlayer->GetMoveType()) {
		case MOVETYPE_NOCLIP:
			vel *= hap_noclip_avatar_scale.GetFloat();
			break;
		default:
			break;
	}

	haptics->UpdateAvatarVelocity(vel);
}
示例#2
0
文件: view.cpp 项目: EspyEspurr/game
static void GetPos( const CCommand &args, Vector &vecOrigin, QAngle &angles )
{
	vecOrigin = MainViewOrigin();
	angles = MainViewAngles();
	if ( args.ArgC() == 2 && atoi( args[1] ) == 2 )
	{
		C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
		if ( pPlayer )
		{
			vecOrigin = pPlayer->GetAbsOrigin();
			angles = pPlayer->GetAbsAngles();
		}
	}
}
示例#3
0
void CreateHairballCallback()
{
	for ( int i=0; i < 20; i++ )
	{
		C_Hairball *pHairball = new C_Hairball;
		pHairball->Init();
		
		// Put it a short distance in front of the player.
		C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
		
		if ( !pPlayer )
			return;

		Vector vForward;
		AngleVectors( pPlayer->GetAbsAngles(), &vForward );
		pHairball->SetLocalOrigin( pPlayer->GetAbsOrigin() + vForward * 300 + RandomVector( 0, 100 ) );
	}
}
示例#4
0
文件: view.cpp 项目: Randdalf/bliink
static void GetPos( const CCommand &args, Vector &vecOrigin, QAngle &angles )
{
	int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
	vecOrigin = MainViewOrigin(nSlot);
	angles = MainViewAngles(nSlot);

#ifdef INFESTED_DLL
	C_ASW_Marine *pMarine = C_ASW_Marine::GetLocalMarine();
	if ( pMarine )
	{
		vecOrigin = pMarine->GetAbsOrigin();
		angles = pMarine->GetAbsAngles();
	}
#endif
	if ( ( args.ArgC() == 2 && atoi( args[1] ) == 2 ) || FStrEq( args[0], "getpos_exact" ) )
	{
		C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
		if ( pPlayer )
		{
			vecOrigin = pPlayer->GetAbsOrigin();
			angles = pPlayer->GetAbsAngles();
		}
	}
}
示例#5
0
文件: view.cpp 项目: EspyEspurr/game
//-----------------------------------------------------------------------------
// Purpose: Moves the client pitch angle towards cl.idealpitch sent by the server.
// If the user is adjusting pitch manually, either with lookup/lookdown,
//   mlook and mouse, or klook and keyboard, pitch drifting is constantly stopped.
//-----------------------------------------------------------------------------
void CViewRender::DriftPitch (void)
{
	float		delta, move;

	C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
	if ( !player )
		return;

#if defined( REPLAY_ENABLED )
	if ( engine->IsHLTV() || g_pEngineClientReplay->IsPlayingReplayDemo() || ( player->GetGroundEntity() == NULL ) || engine->IsPlayingDemo() )
#else
	if ( engine->IsHLTV() || ( player->GetGroundEntity() == NULL ) || engine->IsPlayingDemo() )
#endif
	{
		m_PitchDrift.driftmove = 0;
		m_PitchDrift.pitchvel = 0;
		return;
	}

	// Don't count small mouse motion
	if ( m_PitchDrift.nodrift )
	{
		if ( fabs( input->GetLastForwardMove() ) < cl_forwardspeed.GetFloat() )
		{
			m_PitchDrift.driftmove = 0;
		}
		else
		{
			m_PitchDrift.driftmove += gpGlobals->frametime;
		}
	
		if ( m_PitchDrift.driftmove > v_centermove.GetFloat() )
		{
			StartPitchDrift ();
		}
		return;
	}
	
	// How far off are we
	delta = prediction->GetIdealPitch() - player->GetAbsAngles()[ PITCH ];
	if ( !delta )
	{
		m_PitchDrift.pitchvel = 0;
		return;
	}

	// Determine movement amount
	move = gpGlobals->frametime * m_PitchDrift.pitchvel;
	// Accelerate
	m_PitchDrift.pitchvel += gpGlobals->frametime * v_centerspeed.GetFloat();
	
	// Move predicted pitch appropriately
	if (delta > 0)
	{
		if ( move > delta )
		{
			m_PitchDrift.pitchvel = 0;
			move = delta;
		}
		player->SetLocalAngles( player->GetLocalAngles() + QAngle( move, 0, 0 ) );
	}
	else if ( delta < 0 )
	{
		if ( move > -delta )
		{
			m_PitchDrift.pitchvel = 0;
			move = -delta;
		}
		player->SetLocalAngles( player->GetLocalAngles() - QAngle( move, 0, 0 ) );
	}
}
void C_EnvProjectedTexture::UpdateLight( void )
{
	VPROF("C_EnvProjectedTexture::UpdateLight");
	bool bVisible = true;

	Vector vLinearFloatLightColor( m_LightColor.r, m_LightColor.g, m_LightColor.b );
	float flLinearFloatLightAlpha = m_LightColor.a;

	if ( m_bAlwaysUpdate )
	{
		m_bForceUpdate = true;
	}

	if ( m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha )
	{
		float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f;

		m_CurrentLinearFloatLightColor.x = Approach( vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed );
		m_CurrentLinearFloatLightColor.y = Approach( vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed );
		m_CurrentLinearFloatLightColor.z = Approach( vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed );
		m_flCurrentLinearFloatLightAlpha = Approach( flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed );

		m_bForceUpdate = true;
	}
	
	if ( !m_bForceUpdate )
	{
		bVisible = IsBBoxVisible();		
	}

	if ( m_bState == false || !bVisible )
	{
		// Spotlight's extents aren't in view
		ShutDownLightHandle();

		return;
	}

	if ( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE || m_hTargetEntity != NULL || m_bForceUpdate )
	{
		Vector vForward, vRight, vUp, vPos = GetAbsOrigin();
		FlashlightState_t state;

		if ( m_hTargetEntity != NULL )
		{
			if ( m_bCameraSpace )
			{
				const QAngle &angles = GetLocalAngles();

				C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
				if( pPlayer )
				{
					const QAngle playerAngles = pPlayer->GetAbsAngles();

					Vector vPlayerForward, vPlayerRight, vPlayerUp;
					AngleVectors( playerAngles, &vPlayerForward, &vPlayerRight, &vPlayerUp );

					matrix3x4_t	mRotMatrix;
					AngleMatrix( angles, mRotMatrix );

					VectorITransform( vPlayerForward, mRotMatrix, vForward );
					VectorITransform( vPlayerRight, mRotMatrix, vRight );
					VectorITransform( vPlayerUp, mRotMatrix, vUp );

					float dist = (m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin()).Length();
					vPos = m_hTargetEntity->GetAbsOrigin() - vForward*dist;

					VectorNormalize( vForward );
					VectorNormalize( vRight );
					VectorNormalize( vUp );
				}
			}
			else
			{
				vForward = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin();
				VectorNormalize( vForward );

				// JasonM - unimplemented
				Assert (0);

				//Quaternion q = DirectionToOrientation( dir );


				//
				// JasonM - set up vRight, vUp
				//

				//			VectorNormalize( vRight );
				//			VectorNormalize( vUp );
			}
		}
		else
		{
			AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp );
		}

		state.m_fHorizontalFOVDegrees = m_flLightFOV;
		state.m_fVerticalFOVDegrees = m_flLightFOV;

		state.m_vecLightOrigin = vPos;
		BasisToQuaternion( vForward, vRight, vUp, state.m_quatOrientation );
		state.m_NearZ = m_flNearZ;
		state.m_FarZ = m_flFarZ;

		// quickly check the proposed light's bbox against the view frustum to determine whether we
		// should bother to create it, if it doesn't exist, or cull it, if it does.
		if ( m_bSimpleProjection == false )
		{
#pragma message("OPTIMIZATION: this should be made SIMD")
			// get the half-widths of the near and far planes, 
			// based on the FOV which is in degrees. Remember that
			// on planet Valve, x is forward, y left, and z up. 
			const float tanHalfAngle = tan( m_flLightFOV * ( M_PI/180.0f ) * 0.5f );
			const float halfWidthNear = tanHalfAngle * m_flNearZ;
			const float halfWidthFar = tanHalfAngle * m_flFarZ;
			// now we can build coordinates in local space: the near rectangle is eg 
			// (0, -halfWidthNear, -halfWidthNear), (0,  halfWidthNear, -halfWidthNear), 
			// (0,  halfWidthNear,  halfWidthNear), (0, -halfWidthNear,  halfWidthNear)

			VectorAligned vNearRect[4] = { 
				VectorAligned( m_flNearZ, -halfWidthNear, -halfWidthNear), VectorAligned( m_flNearZ,  halfWidthNear, -halfWidthNear),
				VectorAligned( m_flNearZ,  halfWidthNear,  halfWidthNear), VectorAligned( m_flNearZ, -halfWidthNear,  halfWidthNear) 
			};

			VectorAligned vFarRect[4] = { 
				VectorAligned( m_flFarZ, -halfWidthFar, -halfWidthFar), VectorAligned( m_flFarZ,  halfWidthFar, -halfWidthFar),
				VectorAligned( m_flFarZ,  halfWidthFar,  halfWidthFar), VectorAligned( m_flFarZ, -halfWidthFar,  halfWidthFar) 
			};

			matrix3x4_t matOrientation( vForward, -vRight, vUp, vPos );

			enum
			{
				kNEAR = 0,
				kFAR = 1,
			};
			VectorAligned vOutRects[2][4];

			for ( int i = 0 ; i < 4 ; ++i )
			{
				VectorTransform( vNearRect[i].Base(), matOrientation, vOutRects[0][i].Base() );
			}
			for ( int i = 0 ; i < 4 ; ++i )
			{
				VectorTransform( vFarRect[i].Base(), matOrientation, vOutRects[1][i].Base() );
			}

			// now take the MIN and MAX extents for the bbox, and see if it is visible.
			Vector mins = **vOutRects; 
			Vector maxs = **vOutRects; 
			for ( int i = 1; i < 8 ; ++i )
			{
				VectorMin( mins, *(*vOutRects+i), mins );
				VectorMax( maxs, *(*vOutRects+i), maxs );
			}

#if 0 //for debugging the visibility frustum we just calculated
			NDebugOverlay::Triangle( vOutRects[0][0], vOutRects[0][1], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f ); //first tri
			NDebugOverlay::Triangle( vOutRects[0][2], vOutRects[0][1], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f ); //make it double sided
			NDebugOverlay::Triangle( vOutRects[0][2], vOutRects[0][3], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f ); //second tri
			NDebugOverlay::Triangle( vOutRects[0][0], vOutRects[0][3], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f ); //make it double sided

			NDebugOverlay::Triangle( vOutRects[1][0], vOutRects[1][1], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f ); //first tri
			NDebugOverlay::Triangle( vOutRects[1][2], vOutRects[1][1], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f ); //make it double sided
			NDebugOverlay::Triangle( vOutRects[1][2], vOutRects[1][3], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f ); //second tri
			NDebugOverlay::Triangle( vOutRects[1][0], vOutRects[1][3], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f ); //make it double sided

			NDebugOverlay::Box( vec3_origin, mins, maxs, 0, 255, 0, 100, 0.0f );
#endif
			
			bool bVisible = IsBBoxVisible( mins, maxs );
			if (!bVisible)
			{
				// Spotlight's extents aren't in view
				if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
				{
					ShutDownLightHandle();
				}

				return;
			}
		}

		float flAlpha = m_flCurrentLinearFloatLightAlpha * ( 1.0f / 255.0f );

		state.m_fQuadraticAtten = 0.0;
		state.m_fLinearAtten = 100;
		state.m_fConstantAtten = 0.0f;
		state.m_FarZAtten = m_flFarZ;
		state.m_fBrightnessScale = m_flBrightnessScale;
		state.m_Color[0] = m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * flAlpha;
		state.m_Color[1] = m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * flAlpha;
		state.m_Color[2] = m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * flAlpha;
		state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient;
		state.m_flShadowSlopeScaleDepthBias = g_pMaterialSystemHardwareConfig->GetShadowSlopeScaleDepthBias();
		state.m_flShadowDepthBias = g_pMaterialSystemHardwareConfig->GetShadowDepthBias();
		state.m_bEnableShadows = m_bEnableShadows;
		state.m_pSpotlightTexture = m_SpotlightTexture;
		state.m_pProjectedMaterial = NULL; // only complain if we're using material projection
		state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame;
		state.m_flProjectionSize = m_flProjectionSize;
		state.m_flProjectionRotation = m_flRotation;

		state.m_nShadowQuality = m_nShadowQuality; // Allow entity to affect shadow quality

		if ( m_bSimpleProjection == true )
		{
			state.m_bSimpleProjection = true;
			state.m_bOrtho = true;
			state.m_fOrthoLeft = -m_flProjectionSize;
			state.m_fOrthoTop = -m_flProjectionSize;
			state.m_fOrthoRight = m_flProjectionSize;
			state.m_fOrthoBottom = m_flProjectionSize;
		}

		if( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE )
		{
			// Hack: env projected textures don't work like normal flashlights; they're not assigned to a given splitscreen slot,
			// but the flashlight code requires this
			HACK_GETLOCALPLAYER_GUARD( "Env projected texture" );
			if ( m_bSimpleProjection == true )
			{
				m_LightHandle = g_pClientShadowMgr->CreateProjection( state );
			}
			else
			{
				m_LightHandle = g_pClientShadowMgr->CreateFlashlight( state );
			}

			if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
			{
				m_bForceUpdate = false;
			}
		}
		else
		{
			if ( m_bSimpleProjection == true )
			{
				g_pClientShadowMgr->UpdateProjectionState( m_LightHandle, state );
			}
			else
			{
				g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state );
			}
			m_bForceUpdate = false;
		}

		g_pClientShadowMgr->GetFrustumExtents( m_LightHandle, m_vecExtentsMin, m_vecExtentsMax );

		m_vecExtentsMin = m_vecExtentsMin - GetAbsOrigin();
		m_vecExtentsMax = m_vecExtentsMax - GetAbsOrigin();
	}

	if( m_bLightOnlyTarget )
	{
		g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, m_hTargetEntity );
	}
	else
	{
		g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, NULL );
	}

	g_pClientShadowMgr->SetFlashlightLightWorld( m_LightHandle, m_bLightWorld );

	if ( !asw_perf_wtf.GetBool() && !m_bForceUpdate )
	{
		g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true );
	}
}
void C_EnvProjectedTexture::UpdateLight( bool bForceUpdate )
{
	if ( m_bState == false )
	{
		if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
		{
			ShutDownLightHandle();
		}

		return;
	}

	Vector vForward, vRight, vUp, vPos = GetAbsOrigin();
	FlashlightState_t state;

	if ( m_hTargetEntity != NULL )
	{
		if ( m_bCameraSpace )
		{
			const QAngle &angles = GetLocalAngles();

			C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
			if( pPlayer )
			{
				const QAngle playerAngles = pPlayer->GetAbsAngles();
				
				Vector vPlayerForward, vPlayerRight, vPlayerUp;
				AngleVectors( playerAngles, &vPlayerForward, &vPlayerRight, &vPlayerUp );

            	matrix3x4_t	mRotMatrix;
				AngleMatrix( angles, mRotMatrix );

				VectorITransform( vPlayerForward, mRotMatrix, vForward );
				VectorITransform( vPlayerRight, mRotMatrix, vRight );
				VectorITransform( vPlayerUp, mRotMatrix, vUp );

				float dist = (m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin()).Length();
				vPos = m_hTargetEntity->GetAbsOrigin() - vForward*dist;

				VectorNormalize( vForward );
				VectorNormalize( vRight );
				VectorNormalize( vUp );
			}
		}
		else
		{
			// VXP: Fixing targeting
			Vector vecToTarget;
			QAngle vecAngles;
			if ( m_hTargetEntity == NULL )
			{
			vecAngles = GetAbsAngles();
			}
			else
			{
			vecToTarget = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin();
			VectorAngles( vecToTarget, vecAngles );
			}
			AngleVectors( vecAngles, &vForward, &vRight, &vUp );
		}
	}
	else
	{
		AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp );
	}

	state.m_fHorizontalFOVDegrees = m_flLightFOV;
	state.m_fVerticalFOVDegrees = m_flLightFOV;

	state.m_vecLightOrigin = vPos;
	BasisToQuaternion( vForward, vRight, vUp, state.m_quatOrientation );

	state.m_fQuadraticAtten = 0.0;
	state.m_fLinearAtten = 100;
	state.m_fConstantAtten = 0.0f;
	state.m_Color[0] = m_LinearFloatLightColor.x;
	state.m_Color[1] = m_LinearFloatLightColor.y;
	state.m_Color[2] = m_LinearFloatLightColor.z;
	state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient;
	state.m_NearZ = m_flNearZ;
	state.m_FarZ = m_flFarZ;
	state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat();
	state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat();
	state.m_bEnableShadows = m_bEnableShadows;
	state.m_pSpotlightTexture = materials->FindTexture( m_SpotlightTextureName, TEXTURE_GROUP_OTHER, false );
	state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame;

	state.m_nShadowQuality = m_nShadowQuality; // Allow entity to affect shadow quality

	if( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE )
	{
		m_LightHandle = g_pClientShadowMgr->CreateFlashlight( state );
	}
	else
	{
		if ( m_hTargetEntity != NULL || bForceUpdate == true )
		{
			g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state );
		}
	}

	if( m_bLightOnlyTarget )
	{
		g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, m_hTargetEntity );
	}
	else
	{
		g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, NULL );
	}

	g_pClientShadowMgr->SetFlashlightLightWorld( m_LightHandle, m_bLightWorld );

	//if ( bForceUpdate == false )
	//{
		g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true );
	//}
}
示例#8
0
void CMumbleSystem::PostRender()
{
#ifndef NO_STEAM
	if ( !g_pMumbleMemory || !sv_mumble_positionalaudio.GetBool() )
		return;

	if ( g_pMumbleMemory->uiVersion != 2 )
	{
		V_wcscpy_safe( g_pMumbleMemory->name, L"Source engine: " );
		wchar_t wcsGameDir[MAX_PATH];
		Q_UTF8ToUnicode( COM_GetModDirectory(), wcsGameDir, sizeof(wcsGameDir) );
		V_wcscat_safe( g_pMumbleMemory->name, wcsGameDir );

		V_wcscpy_safe( g_pMumbleMemory->description, L"Links Source engine games to Mumble." );
		g_pMumbleMemory->uiVersion = 2;
	}

	g_pMumbleMemory->uiTick++;

	Vector vecOriginPlayer, vecOriginCamera = MainViewOrigin();
	QAngle anglesPlayer, anglesCamera = MainViewAngles();

	C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
	if ( pPlayer )
	{
		vecOriginPlayer = pPlayer->EyePosition();
		anglesPlayer = pPlayer->GetAbsAngles();
	}
	else
	{
		vecOriginPlayer = vecOriginCamera;
		anglesPlayer = anglesCamera;
	}

	anglesPlayer.x = 0;

	Vector vecPlayerForward, vecPlayerUp, vecCameraForward, vecCameraUp;
	AngleVectors( anglesPlayer, &vecPlayerForward, NULL, &vecPlayerUp );
	AngleVectors( anglesCamera, &vecCameraForward, NULL, &vecCameraUp );

	// 1 Source unit is about one inch
	// 1 mumble unit = 1 meter
	vecOriginPlayer *= METERS_PER_INCH;
	vecOriginCamera *= METERS_PER_INCH;

	VectorToMumbleFloatArray( vecPlayerForward, g_pMumbleMemory->fAvatarFront );
	VectorToMumbleFloatArray( vecPlayerUp, g_pMumbleMemory->fAvatarTop );
	VectorToMumbleFloatArray( vecOriginPlayer, g_pMumbleMemory->fAvatarPosition );

	VectorToMumbleFloatArray( vecCameraForward, g_pMumbleMemory->fCameraFront );
	VectorToMumbleFloatArray( vecCameraUp, g_pMumbleMemory->fCameraTop );
	VectorToMumbleFloatArray( vecOriginCamera, g_pMumbleMemory->fCameraPosition );

	if ( pPlayer && m_bHasSetPlayerUniqueId && m_nTeamSetInUniqueId != pPlayer->GetTeamNumber() )
	{
		// Player changed team since we set the unique ID. Set it again.
		m_bHasSetPlayerUniqueId = false;
	}

	if ( !m_bHasSetPlayerUniqueId && steamapicontext && steamapicontext->SteamUser() )
	{
		CSteamID steamid = steamapicontext->SteamUser()->GetSteamID();
		if ( steamid.IsValid() )
		{
			int unTeam = pPlayer ? pPlayer->GetTeamNumber() : 0;
			char szSteamId[256];
			V_sprintf_safe( szSteamId, "universe:%u;account_type:%u;id:%u;instance:%u;team:%d", steamid.GetEUniverse(), steamid.GetEAccountType(), steamid.GetAccountID(), steamid.GetUnAccountInstance(), unTeam );

			wchar_t wcsSteamId[256];
			Q_UTF8ToUnicode( szSteamId, wcsSteamId, sizeof(wcsSteamId) );

			// Identifier which uniquely identifies a certain player in a context.
			V_wcscpy_safe( g_pMumbleMemory->identity, wcsSteamId );

			m_bHasSetPlayerUniqueId = true;
			m_nTeamSetInUniqueId = unTeam;
		}
	}

	// Context should be equal for players which should be able to hear each other positional and
	// differ for those who shouldn't (e.g. it could contain the server+port and team)
	memcpy( g_pMumbleMemory->context, &m_szSteamIDCurrentServer, m_cubSteamIDCurrentServer );
	g_pMumbleMemory->context_len = m_cubSteamIDCurrentServer;
#endif // NO_STEAM
}
void C_EnvProjectedTexture::UpdateLight(void)
{
	VPROF_BUDGET("C_EnvProjectedTexture::UpdateLight", "Projected Textures");

	if (CurrentViewID() == VIEW_SHADOW_DEPTH_TEXTURE /*|| CurrentViewID() == VIEW_SUN_SHAFTS*/)
		return;

	bool bVisible = true;

	if (m_bAlwaysUpdate)
	{
		m_bForceUpdate = true;
	}

	float fHighFOV;
	if (m_flLightFOV > m_flLightHorFOV)
		fHighFOV = m_flLightFOV;
	else
		fHighFOV = m_flLightHorFOV;

	if (m_bState == false || !IsWithinFarZ(fHighFOV) || !IsBBoxVisible())
	{
		// Spotlight's extents aren't in view
		ShutDownLightHandle();

		return;
	}
	else
	{
		bVisible = true;
	}

	Vector vLinearFloatLightColor(m_LightColor.r, m_LightColor.g, m_LightColor.b);
	float flLinearFloatLightAlpha = m_LightColor.a;

	if (m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha)
	{
		float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f;

		m_CurrentLinearFloatLightColor.x = Approach(vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed);
		m_CurrentLinearFloatLightColor.y = Approach(vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed);
		m_CurrentLinearFloatLightColor.z = Approach(vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed);
		m_flCurrentLinearFloatLightAlpha = Approach(flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed);

		m_bForceUpdate = true;
	}

	if (m_LightHandle == CLIENTSHADOW_INVALID_HANDLE || m_hTargetEntity != NULL || GetRootMoveParent() != NULL || m_bForceUpdate)
	{
		Vector vForward, vRight, vUp, vPos = GetAbsOrigin();
		FlashlightState_t state;

		if (m_hTargetEntity != NULL)
		{
			if (m_bCameraSpace)
			{
				const QAngle &angles = GetLocalAngles();

				C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
				if (pPlayer)
				{
					const QAngle playerAngles = pPlayer->GetAbsAngles();

					Vector vPlayerForward, vPlayerRight, vPlayerUp;
					AngleVectors(playerAngles, &vPlayerForward, &vPlayerRight, &vPlayerUp);

					matrix3x4_t	mRotMatrix;
					AngleMatrix(angles, mRotMatrix);

					VectorITransform(vPlayerForward, mRotMatrix, vForward);
					VectorITransform(vPlayerRight, mRotMatrix, vRight);
					VectorITransform(vPlayerUp, mRotMatrix, vUp);

					float dist = (m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin()).Length();
					vPos = m_hTargetEntity->GetAbsOrigin() - vForward*dist;

					VectorNormalize(vForward);
					VectorNormalize(vRight);
					VectorNormalize(vUp);
				}
			}
			else
			{
				Vector vecToTarget = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin();
				QAngle vecAngles;
				VectorAngles(vecToTarget, vecAngles);
				AngleVectors(vecAngles, &vForward, &vRight, &vUp);
			}
		}
		else
		{
			AngleVectors(GetAbsAngles(), &vForward, &vRight, &vUp);
		}

		state.m_fHorizontalFOVDegrees = abs(m_flLightHorFOV);
		state.m_fVerticalFOVDegrees = abs(m_flLightFOV);

		state.m_vecLightOrigin = vPos;
		BasisToQuaternion(vForward, vRight, vUp, state.m_quatOrientation);
		state.m_NearZ = m_flNearZ;
		state.m_FarZ = m_flFarZ;

		// quickly check the proposed light's bbox against the view frustum to determine whether we
		// should bother to create it, if it doesn't exist, or cull it, if it does.
		// get the half-widths of the near and far planes, 
		// based on the FOV which is in degrees. Remember that
		// on planet Valve, x is forward, y left, and z up. 
		const float tanHalfAngle = tan(fHighFOV * (M_PI / 180.0f) * 0.5f);
		const float halfWidthNear = tanHalfAngle * m_flNearZ;
		const float halfWidthFar = tanHalfAngle * m_flFarZ;
		// now we can build coordinates in local space: the near rectangle is eg 
		// (0, -halfWidthNear, -halfWidthNear), (0,  halfWidthNear, -halfWidthNear), 
		// (0,  halfWidthNear,  halfWidthNear), (0, -halfWidthNear,  halfWidthNear)

		VectorAligned vNearRect[4] = {
			VectorAligned(m_flNearZ, -halfWidthNear, -halfWidthNear), VectorAligned(m_flNearZ,  halfWidthNear, -halfWidthNear),
			VectorAligned(m_flNearZ,  halfWidthNear,  halfWidthNear), VectorAligned(m_flNearZ, -halfWidthNear,  halfWidthNear)
		};

		VectorAligned vFarRect[4] = {
			VectorAligned(m_flFarZ, -halfWidthFar, -halfWidthFar), VectorAligned(m_flFarZ,  halfWidthFar, -halfWidthFar),
			VectorAligned(m_flFarZ,  halfWidthFar,  halfWidthFar), VectorAligned(m_flFarZ, -halfWidthFar,  halfWidthFar)
		};

		matrix3x4_t matOrientation(vForward, -vRight, vUp, vPos);

		enum
		{
			kNEAR = 0,
			kFAR = 1,
		};
		VectorAligned vOutRects[2][4];

		for (int i = 0; i < 4; ++i)
		{
			VectorTransform(vNearRect[i].Base(), matOrientation, vOutRects[0][i].Base());
		}
		for (int i = 0; i < 4; ++i)
		{
			VectorTransform(vFarRect[i].Base(), matOrientation, vOutRects[1][i].Base());
		}

		// now take the min and max extents for the bbox, and see if it is visible.
		Vector mins = **vOutRects;
		Vector maxs = **vOutRects;
		for (int i = 1; i < 8; ++i)
		{
			VectorMin(mins, *(*vOutRects + i), mins);
			VectorMax(maxs, *(*vOutRects + i), maxs);
		}

#if 0 //for debugging the visibility frustum we just calculated
		NDebugOverlay::Triangle(vOutRects[0][0], vOutRects[0][1], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f); //first tri
		NDebugOverlay::Triangle(vOutRects[0][2], vOutRects[0][1], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f); //make it double sided
		NDebugOverlay::Triangle(vOutRects[0][2], vOutRects[0][3], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f); //second tri
		NDebugOverlay::Triangle(vOutRects[0][0], vOutRects[0][3], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f); //make it double sided

		NDebugOverlay::Triangle(vOutRects[1][0], vOutRects[1][1], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f); //first tri
		NDebugOverlay::Triangle(vOutRects[1][2], vOutRects[1][1], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f); //make it double sided
		NDebugOverlay::Triangle(vOutRects[1][2], vOutRects[1][3], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f); //second tri
		NDebugOverlay::Triangle(vOutRects[1][0], vOutRects[1][3], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f); //make it double sided

		NDebugOverlay::Box(vec3_origin, mins, maxs, 0, 255, 0, 100, 0.0f);
#endif

		bool bVisible = IsBBoxVisible(mins, maxs);
		if (!bVisible)
		{
			// Spotlight's extents aren't in view
			if (m_LightHandle != CLIENTSHADOW_INVALID_HANDLE)
			{
				ShutDownLightHandle();
			}

			return;
		}

		float flAlpha = m_flCurrentLinearFloatLightAlpha * (1.0f / 255.0f);

		state.m_fQuadraticAtten = m_flQuadratic;
		state.m_fLinearAtten = 100;
		if (m_bAtten)
		{
			state.m_fConstantAtten = 0.0f;
		}
		else
		{
			state.m_fConstantAtten = 1.0f;
		}
		state.m_Color[0] = (m_CurrentLinearFloatLightColor.x * (1.0f / 255.0f) * flAlpha) * m_fBrightness;
		state.m_Color[1] = (m_CurrentLinearFloatLightColor.y * (1.0f / 255.0f) * flAlpha) * m_fBrightness;
		state.m_Color[2] = (m_CurrentLinearFloatLightColor.z * (1.0f / 255.0f) * flAlpha) * m_fBrightness;
		state.m_Color[3] = m_flAmbient;
		state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat();
		state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat();
		if (m_bEnableShadows && r_flashlightdepthtexture.GetBool() && m_bClientWantsShadows)
		{
			state.m_bEnableShadows = true;
		}
		else
		{
			state.m_bEnableShadows = false;
		}
		state.m_pSpotlightTexture = m_SpotlightTexture;
		state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame;
		if (r_dynamicshadows_use_c17_improvements.GetBool())
		{
			//state.m_flShadowFilterSize = m_flBlur;
			if (r_flashlightdepthres.GetInt() == 512)
			{
				state.m_flShadowFilterSize = 0.8f;
			}
			else if (r_flashlightdepthres.GetInt() == 1024)
			{
				state.m_flShadowFilterSize = 0.3f;
			}
			else if (r_flashlightdepthres.GetInt() == 2048)
			{
				state.m_flShadowFilterSize = 0.2f;
			}
			else if (r_flashlightdepthres.GetInt() == 4096)
			{
				state.m_flShadowFilterSize = 0.08f;
			}
			else
			{
				state.m_flShadowFilterSize = 1.0f;
			}
			state.m_flShadowAtten = m_flAtten;
		}
		else
		{
			state.m_flShadowFilterSize = 3.0f;
			state.m_flShadowAtten = 0.35f;
		}
		state.m_nShadowQuality = m_nShadowQuality; // Allow entity to affect shadow quality

		if (m_LightHandle == CLIENTSHADOW_INVALID_HANDLE)
		{
			// Hack: env projected textures don't work like normal flashlights; they're not assigned to a given splitscreen slot,
			// but the flashlight code requires this
			m_LightHandle = g_pClientShadowMgr->CreateFlashlight(state);

			if (m_LightHandle != CLIENTSHADOW_INVALID_HANDLE)
			{
				m_bForceUpdate = false;
			}
		}
		else
		{
			g_pClientShadowMgr->UpdateFlashlightState(m_LightHandle, state);
			m_bForceUpdate = false;
		}

		g_pClientShadowMgr->GetFrustumExtents(m_LightHandle, m_vecExtentsMin, m_vecExtentsMax);

		m_vecExtentsMin = m_vecExtentsMin - GetAbsOrigin();
		m_vecExtentsMax = m_vecExtentsMax - GetAbsOrigin();
	}

	if (m_bLightOnlyTarget)
	{
		g_pClientShadowMgr->SetFlashlightTarget(m_LightHandle, m_hTargetEntity);
	}
	else
	{
		g_pClientShadowMgr->SetFlashlightTarget(m_LightHandle, NULL);
	}

	g_pClientShadowMgr->SetFlashlightLightWorld(m_LightHandle, m_bLightWorld);

	if (!m_bForceUpdate)
	{
		g_pClientShadowMgr->UpdateProjectedTexture(m_LightHandle, true);
	}
}