Beispiel #1
0
//-----------------------------------------------------------------------------
// Purpose: Save CPU cycles by letting the HUD system early cull
// costly traversal.  Called per frame, return true if thinking and 
// painting need to occur.
//-----------------------------------------------------------------------------
bool CHudCrosshair::ShouldDraw( void )
{
	bool bNeedsDraw;

	C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer();
	if ( !pPlayer )
		return false;

	// draw a crosshair only if alive or spectating in eye
	if ( IsXbox() )
	{
		bNeedsDraw = m_pCrosshair && 
			!engine->IsDrawingLoadingImage() &&
			!engine->IsPaused() && 
			!pPlayer->IsSuitEquipped() &&
			g_pClientMode->ShouldDrawCrosshair() &&
			!( pPlayer->GetFlags() & FL_FROZEN ) &&
			( pPlayer->entindex() == render->GetViewEntity() ) &&
			( pPlayer->IsAlive() ||	( pPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) || ( cl_observercrosshair.GetBool() && pPlayer->GetObserverMode() == OBS_MODE_ROAMING ) );
	}
	else
	{
		bNeedsDraw = m_pCrosshair && 
			crosshair.GetInt() &&
			!engine->IsDrawingLoadingImage() &&
			!engine->IsPaused() && 
			g_pClientMode->ShouldDrawCrosshair() &&
			!( pPlayer->GetFlags() & FL_FROZEN ) &&
			( pPlayer->entindex() == render->GetViewEntity() ) &&
			( pPlayer->IsAlive() ||	( pPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) || ( cl_observercrosshair.GetBool() && pPlayer->GetObserverMode() == OBS_MODE_ROAMING ) );
	}

	return ( bNeedsDraw && CHudElement::ShouldDraw() );
}
//-----------------------------------------------------------------------------
// Purpose: Save CPU cycles by letting the HUD system early cull
// costly traversal.  Called per frame, return true if thinking and 
// painting need to occur.
//-----------------------------------------------------------------------------
bool CHudCrosshair::ShouldDraw( void )
{
	bool bNeedsDraw;

	if ( m_bHideCrosshair )
		return false;

	C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer();
	if ( !pPlayer )
		return false;

	C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon();
	if ( pWeapon && !pWeapon->ShouldDrawCrosshair() )
		return false;

#ifdef PORTAL
	C_Portal_Player *portalPlayer = ToPortalPlayer(pPlayer);
	if ( portalPlayer && portalPlayer->IsSuppressingCrosshair() )
		return false;
#endif // PORTAL

	/* disabled to avoid assuming it's an HL2 player.
	// suppress crosshair in zoom.
	if ( pPlayer->m_HL2Local.m_bZooming )
		return false;
	*/

	// draw a crosshair only if alive or spectating in eye
	if ( IsX360() )
	{
		bNeedsDraw = m_pCrosshair && 
			!engine->IsDrawingLoadingImage() &&
			!engine->IsPaused() && 
			( !pPlayer->IsSuitEquipped() || g_pGameRules->IsMultiplayer() ) &&
			g_pClientMode->ShouldDrawCrosshair() &&
			!( pPlayer->GetFlags() & FL_FROZEN ) &&
			( pPlayer->entindex() == render->GetViewEntity() ) &&
			( pPlayer->IsAlive() ||	( pPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) || ( cl_observercrosshair.GetBool() && pPlayer->GetObserverMode() == OBS_MODE_ROAMING ) );
	}
	else
	{
		bNeedsDraw = m_pCrosshair && 
			crosshair.GetInt() &&
			!engine->IsDrawingLoadingImage() &&
			!engine->IsPaused() && 
			g_pClientMode->ShouldDrawCrosshair() &&
			!( pPlayer->GetFlags() & FL_FROZEN ) &&
			( pPlayer->entindex() == render->GetViewEntity() ) &&
			!pPlayer->IsInVGuiInputMode() &&
			( pPlayer->IsAlive() ||	( pPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) || ( cl_observercrosshair.GetBool() && pPlayer->GetObserverMode() == OBS_MODE_ROAMING ) );
	}

	return ( bNeedsDraw && CHudElement::ShouldDraw() );
}
Beispiel #3
0
//-----------------------------------------------------------------------------
// Purpose: Return true if the passed in sections of the HUD shouldn't be drawn
//-----------------------------------------------------------------------------
bool CHud::IsHidden(int iHudFlags)
{
    // Not in game?
    if (!engine->IsInGame())
        return true;

    // No local player yet?
    C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
    if (!pPlayer)
        return true;

    // Get current hidden flags
    int iHideHud = pPlayer->m_Local.m_iHideHUD;
    if (hidehud.GetInt())
    {
        iHideHud = hidehud.GetInt();
    }

    // Everything hidden?
    if (iHideHud & HIDEHUD_ALL)
        return true;

    // Local player dead?
    if ((iHudFlags & HIDEHUD_PLAYERDEAD) && (pPlayer->GetHealth() <= 0 && !pPlayer->IsAlive()))
        return true;

    // Need the HEV suit ( HL2 )
    if ((iHudFlags & HIDEHUD_NEEDSUIT) && (!pPlayer->IsSuitEquipped()))
        return true;

    return ((iHudFlags & iHideHud) != 0);
}
void ClientModeSDKNormal::OverrideView( CViewSetup *pSetup )
{
	QAngle camAngles;

	// Let the player override the view.
	C_BasePlayer *pPlayer = C_SDKPlayer::GetLocalOrSpectatedPlayer();
	if(!pPlayer)
		return;

	pPlayer->OverrideView( pSetup );

	if( ::input->CAM_IsThirdPerson() && pPlayer->IsAlive() )
	{
		Vector cam_ofs = g_ThirdPersonManager.GetCameraOffsetAngles();

		camAngles[ PITCH ] = cam_ofs[ PITCH ];
		camAngles[ YAW ] = cam_ofs[ YAW ];
		camAngles[ ROLL ] = 0;

		Vector camForward, camRight, camUp;
		AngleVectors( camAngles, &camForward, &camRight, &camUp );

		VectorMA( pSetup->origin, -cam_ofs[ ROLL ], camForward, pSetup->origin );

		// Override angles from third person camera
		float flRoll = pSetup->angles.z;
		pSetup->angles = camAngles;
		pSetup->angles.z = flRoll;
	}
}
Beispiel #5
0
void CViewRender::ApplyHeadShake(CViewSetup *view)
{
	CameraOffsets shake = UTIL_GetHandycamShake();

	view->angles[PITCH]		-= shake.pitch;
	view->angles[YAW]		+= shake.yaw;
	view->angles[ROLL]		-= shake.roll;
	
	float width		=     CMS_TO_SOURCE(shake.horOff);
	float height	= max(CMS_TO_SOURCE(shake.vertOff), 0);

	view->origin.y += width * cos(DEG_TO_RAD(view->angles[YAW]));
	view->origin.x -= width * sin(DEG_TO_RAD(view->angles[YAW]));
	view->origin.z += height;

	C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();

	if(pPlayer && pPlayer->IsAlive())
	{
		float aspectRatio	  = engine->GetScreenAspectRatio() * 0.75f;
		float leanFov		  = fabs(UTIL_GetLeanAmount()) * hal_leanFOV.GetFloat() * aspectRatio;
		view->fov			 -= leanFov;
		view->fovViewmodel	 -= leanFov;
	}
}
//-----------------------------------------------------------------------------
// Purpose: Save CPU cycles by letting the HUD system early cull
// costly traversal.  Called per frame, return true if thinking and 
// painting need to occur.
//-----------------------------------------------------------------------------
bool CDAHudCrosshair::ShouldDraw( void )
{
	// OnThink isn't called when the thing isn't visible so force it to update.
	CalculateCrosshair();

	bool bNeedsDraw;

	if ( m_bHideCrosshair )
		return false;

	C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer();
	if ( !pPlayer )
		return false;

	C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon();
	if ( pWeapon && !pWeapon->ShouldDrawCrosshair() )
		return false;

	ConVarRef cl_observercrosshair("cl_observercrosshair");

	// draw a crosshair only if alive or spectating in eye
	if ( IsX360() )
	{
		bNeedsDraw = m_pCrosshair && 
			!engine->IsDrawingLoadingImage() &&
			!engine->IsPaused() && 
			( !pPlayer->IsSuitEquipped() || g_pGameRules->IsMultiplayer() ) &&
			g_pClientMode->ShouldDrawCrosshair() &&
			!( pPlayer->GetFlags() & FL_FROZEN ) &&
			( pPlayer->entindex() == render->GetViewEntity() ) &&
			( pPlayer->IsAlive() ||	( pPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) || ( cl_observercrosshair.GetBool() && pPlayer->GetObserverMode() == OBS_MODE_ROAMING ) );
	}
	else
	{
		bNeedsDraw = m_pCrosshair && 
			da_crosshair.GetInt() &&
			!engine->IsDrawingLoadingImage() &&
			!engine->IsPaused() && 
			g_pClientMode->ShouldDrawCrosshair() &&
			!( pPlayer->GetFlags() & FL_FROZEN ) &&
			( pPlayer->entindex() == render->GetViewEntity() ) &&
			!pPlayer->IsInVGuiInputMode() &&
			( pPlayer->IsAlive() ||	( pPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) || ( cl_observercrosshair.GetBool() && pPlayer->GetObserverMode() == OBS_MODE_ROAMING ) );
	}

	return ( bNeedsDraw && CHudElement::ShouldDraw() );
}
Beispiel #7
0
void C_CFPlayer::DrawTargets()
{
	if (m_hDirectTarget != m_hDrawingDirectTarget)
	{
		m_hDrawingDirectTarget = m_hDirectTarget;
		m_flReceivedDirectTarget = gpGlobals->curtime;
	}

	if (m_hRecursedTarget != m_hDrawingRecursedTarget)
	{
		m_hDrawingRecursedTarget = m_hRecursedTarget;
		m_flReceivedRecursedTarget = gpGlobals->curtime;
	}

	for (int i = 1; i < gpGlobals->maxClients; i++)
	{
		C_BasePlayer* pPlayer = UTIL_PlayerByIndex(i);

		if (!pPlayer)
			continue;

		C_CFPlayer* pCFPlayer = ToCFPlayer(pPlayer);

		if ( this == pCFPlayer )
			continue;

		if (!pPlayer->IsAlive())
			continue;

		Vector vecTargetPosition = pCFPlayer->GetAbsOrigin() + Vector(0, 0, 10);

		bool bTeammate = CFGameRules() && CFGameRules()->PlayerRelationship(this, pCFPlayer) == GR_TEAMMATE;

		float flWooshTime = 0;
		if (m_hDirectTarget == pCFPlayer)
			flWooshTime = gpGlobals->curtime - m_flReceivedDirectTarget;
		else
			flWooshTime = gpGlobals->curtime - m_flReceivedRecursedTarget;

		if ( (m_hDirectTarget == pCFPlayer || m_hRecursedTarget == pCFPlayer) )
		{
			DrawTarget(bTeammate?"effects/target_friend":"effects/target_enemy", vecTargetPosition, 0, flWooshTime);
		}

		if (m_hDirectTarget == pCFPlayer && m_hRecursedTarget != pCFPlayer && bTeammate)
		{
			QAngle angTarget;
			VectorAngles((m_hRecursedTarget->GetAbsOrigin() - pCFPlayer->GetAbsOrigin()), angTarget);
			DrawTarget(bTeammate?"effects/targeting_friend":"effects/targeting_enemy", vecTargetPosition, angTarget.y, flWooshTime);
		}

		if (pCFPlayer->m_hDirectTarget == this || pCFPlayer->m_hRecursedTarget == this)
		{
			QAngle angTarget;
			VectorAngles((GetAbsOrigin() - pCFPlayer->GetAbsOrigin()), angTarget);
			DrawTarget(bTeammate?"effects/targeting_friend":"effects/targeting_enemy", vecTargetPosition, angTarget.y, flWooshTime);
		}
	}
}
Beispiel #8
0
//---------------------------------------------------------
//---------------------------------------------------------
void UpdateScreenShakeRumble( float shake, float balance )
{
	C_BasePlayer *localPlayer = C_BasePlayer::GetLocalPlayer();
	if( !localPlayer || !localPlayer->IsAlive() )
	{
		return;
	}

	g_RumbleEffects.UpdateScreenShakeRumble( shake, balance );
}
Beispiel #9
0
//---------------------------------------------------------
//---------------------------------------------------------
void UpdateRumbleEffects()
{
	C_BasePlayer *localPlayer = C_BasePlayer::GetLocalPlayer();
	if( !localPlayer || !localPlayer->IsAlive() )
	{
		StopAllRumbleEffects();
		return;
	}

	g_RumbleEffects.UpdateEffects( gpGlobals->curtime );
}
Beispiel #10
0
void OpenVoiceMenu( int index )
{
	// do not show the menu if the player is dead or is an observer
	C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
	if ( !pPlayer )
		return;

	if ( !pPlayer->IsAlive() || pPlayer->IsObserver() )
		return;

	CHudMenu *pMenu = (CHudMenu *) gHUD.FindElement( "CHudMenu" );
	if ( !pMenu )
		return;

	// if they hit the key again, close the menu
	if ( g_ActiveVoiceMenu == index )
	{
		if ( pMenu->IsMenuOpen() )
		{
			pMenu->HideMenu();
			g_ActiveVoiceMenu = 0;
			return;
		}
	}

	if ( index > 0 && index < 9 )
	{
		KeyValues *pKV = new KeyValues( "MenuItems" );

		CMultiplayRules *pRules = dynamic_cast< CMultiplayRules * >( GameRules() );
		if ( pRules )
		{			
			if ( !pRules->GetVoiceMenuLabels( index-1, pKV ) )
			{ 
				pKV->deleteThis();
				return;
			}
		}

		pMenu->ShowMenu_KeyValueItems( pKV );

		pKV->deleteThis();

		g_ActiveVoiceMenu = index;
	}
	else
	{
		g_ActiveVoiceMenu = 0;
	}
}
Beispiel #11
0
//-----------------------------------------------------------------------------
// Purpose: Return true if the passed in sections of the HUD shouldn't be drawn
//-----------------------------------------------------------------------------
bool CHud::IsHidden( int iHudFlags, HUDRENDERSTAGE_t stage ) // GSTRINGMIGRATION
{
	// GSTRINGMIGRATION
	const bool bDrawAll = m_iRenderingStage == HUDRENDERSTAGE_ALL;

	if ( !bDrawAll && stage != m_iRenderingStage )
		return true;
	// END GSTRINGMIGRATION

	// Not in game?
	if ( !engine->IsInGame() )
		return true;

	// No local player yet?
	C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
	if ( !pPlayer )
		return true;

	// Get current hidden flags
	int iHideHud = pPlayer->m_Local.m_iHideHUD;
	if ( hidehud.GetInt() )
	{
		iHideHud = hidehud.GetInt();
	}

	// Everything hidden?
	if ( iHideHud & HIDEHUD_ALL )
		return true;

	// Local player dead?
	if ( ( iHudFlags & HIDEHUD_PLAYERDEAD ) && ( pPlayer->GetHealth() <= 0 && !pPlayer->IsAlive() ) )
		return true;

	// Need the HEV suit ( HL2 )
	if ( ( iHudFlags & HIDEHUD_NEEDSUIT ) && ( !pPlayer->IsSuitEquipped() ) )
		return true;

	// Hide all HUD elements during screenshot if the user's set hud_freezecamhide ( TF2 )
#if defined( TF_CLIENT_DLL )
	extern bool IsTakingAFreezecamScreenshot();
	extern ConVar hud_freezecamhide;

	if ( IsTakingAFreezecamScreenshot() && hud_freezecamhide.GetBool() )
		return true;
#endif

	return ( ( iHudFlags & iHideHud ) != 0);
}
Beispiel #12
0
//-----------------------------------------------------------------------------
// Purpose: Return true if the passed in sections of the HUD shouldn't be drawn
//-----------------------------------------------------------------------------
bool CHud::IsHidden( int iHudFlags )
{
	// Not in game?
	if ( !engine->IsInGame() )
		return true;

	// No local player yet?
	C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
	if ( !pPlayer )
		return true;

	// Get current hidden flags
	int iHideHud = pPlayer->m_Local.m_iHideHUD;
	if ( hidehud.GetInt() )
	{
		iHideHud = hidehud.GetInt();
	}

	// Everything hidden?
	if ( iHideHud & HIDEHUD_ALL )
		return true;

	// Local player dead?
	if ( ( iHudFlags & HIDEHUD_PLAYERDEAD ) && ( pPlayer->GetHealth() <= 0 && !pPlayer->IsAlive() ) )
		return true;

	//BG2 - found this stuff removed while porting to 2016 - Awesome
	/*
	// Need the HEV suit ( HL2 )
	if ( ( iHudFlags & HIDEHUD_NEEDSUIT ) && ( !pPlayer->IsSuitEquipped() ) )
		return true;

	// Hide all HUD elements during screenshot if the user's set hud_freezecamhide ( TF2 )
#if defined( TF_CLIENT_DLL )
	extern bool IsTakingAFreezecamScreenshot();
	extern ConVar hud_freezecamhide;

	if ( IsTakingAFreezecamScreenshot() && hud_freezecamhide.GetBool() )
		return true;
#endif
		*/
	return ( ( iHudFlags & iHideHud ) != 0);
}
Beispiel #13
0
void C_HLTVCamera::CalcInEyeCamView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov )
{
	C_BasePlayer *pPlayer = UTIL_PlayerByIndex( m_iTraget1 );

	if ( !pPlayer )
		return;

	if ( !pPlayer->IsAlive() )
	{
		// if dead, show from 3rd person
		CalcChaseCamView( eyeOrigin, eyeAngles, fov );
		return;
	}

	m_aCamAngle	= pPlayer->EyeAngles();
	m_vCamOrigin = pPlayer->GetAbsOrigin();
	m_flFOV = pPlayer->GetFOV();

	if ( pPlayer->GetFlags() & FL_DUCKING )
	{
		m_vCamOrigin += VEC_DUCK_VIEW;
	}
	else
	{
		m_vCamOrigin += VEC_VIEW;
	}

	eyeOrigin = m_vCamOrigin;
	eyeAngles = m_aCamAngle;
	fov = m_flFOV;

	pPlayer->CalcViewModelView( eyeOrigin, eyeAngles);

	C_BaseViewModel *pViewModel = pPlayer->GetViewModel( 0 );

	if ( pViewModel )
	{
		Assert( pViewModel->GetOwner() == pPlayer );
		pViewModel->UpdateVisibility();
	}
}
void Resolver::Log()
{
	for (int i = 1; i <= g_GlobalVars->maxClients; i++)
	{
		auto &record = arr_infos[i];

		C_BasePlayer *player = C_BasePlayer::GetPlayerByIndex(i);
		if (!player || !player->IsAlive() || player->m_iTeamNum() == g_LocalPlayer->m_iTeamNum())
		{
			record.m_bActive = false;
			continue;
		}

		if (player->IsDormant())
			continue;

		if(record.m_flSimulationTime == player->m_flSimulationTime())
			continue;

		record.SaveRecord(player);
		record.m_bActive = true;
	}
}
//-----------------------------------------------------------------------------
void CSDKMapOverview::Update( void )
{
	C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();

	if ( !pPlayer )
		return;

	int team = pPlayer->GetTeamNumber();

	// if dead with fadetoblack on, we can't show anything
	if ( mp_fadetoblack.GetBool() && team > TEAM_SPECTATOR && !pPlayer->IsAlive() )
	{
		SetMode( MAP_MODE_OFF );
		return;
	}

	BaseClass::Update();

	if ( GetSpectatorMode() == OBS_MODE_CHASE )
	{
		// Follow the local player in chase cam, so the map rotates using the local player's angles
		SetFollowEntity( pPlayer->entindex() );
	}
}
//=========================================================
//=========================================================
bool C_GameInstructor::OpenOpportunity( CBaseLesson *pLesson )
{
	// Get the root lesson
	CBaseLesson *pRootLesson = pLesson->GetRoot();
 
	if ( !pRootLesson )
	{
		if ( gameinstructor_verbose.GetInt() > 0 )
		{
			ConColorMsg( CBaseLesson::m_rgbaVerboseHeader, "[INSTRUCTOR]: " );
			ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "Opportunity " );
			ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\"%s\" ", pLesson->GetName() );
			ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "NOT opened (because root lesson could not be found).\n" );
		}
 
		delete pLesson;
		return false;
	}
 
	C_BasePlayer *pLocalPlayer = GetLocalPlayer();
 
	if ( !pRootLesson->CanOpenWhenDead() && ( !pLocalPlayer || !pLocalPlayer->IsAlive() ) )
	{
		// If the player is dead don't allow lessons that can't be opened when dead
		if ( gameinstructor_verbose.GetInt() > 0 )
		{
			ConColorMsg( CBaseLesson::m_rgbaVerboseHeader, "[INSTRUCTOR]: " );
			ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "Opportunity " );
			ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\"%s\" ", pLesson->GetName() );
			ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "NOT opened (because player is dead and can_open_when_dead not set).\n" );
		}
 
		delete pLesson;
		return false;
	}
 
	if ( !pRootLesson->PrerequisitesHaveBeenMet() )
	{
		// If the prereqs haven't been met, don't open it
		if ( gameinstructor_verbose.GetInt() > 0 )
		{
			ConColorMsg( CBaseLesson::m_rgbaVerboseHeader, "[INSTRUCTOR]: " );
			ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "Opportunity " );
			ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\"%s\" ", pLesson->GetName() );
			ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "NOT opened (because prereqs haven't been met).\n" );
		}
 
		delete pLesson;
		return false;
	}
 
	if ( pRootLesson->InstanceType() == LESSON_INSTANCE_FIXED_REPLACE )
	{
		CBaseLesson *pLessonToReplace = NULL;
		CBaseLesson *pLastReplacableLesson = NULL;
 
		int iInstanceCount = 0;
 
		// Check how many are already open
		for ( int i = m_OpenOpportunities.Count() - 1; i >= 0; --i )
		{
			CBaseLesson *pOpenOpportunity = m_OpenOpportunities[ i ];
 
			if ( pOpenOpportunity->GetNameSymbol() == pLesson->GetNameSymbol() && 
				 pOpenOpportunity->GetReplaceKeySymbol() == pLesson->GetReplaceKeySymbol() )
			{
				iInstanceCount++;
 
				if ( pRootLesson->ShouldReplaceOnlyWhenStopped() )
				{
					if ( !pOpenOpportunity->IsInstructing() )
					{
						pLastReplacableLesson = pOpenOpportunity;
					}
				}
				else
				{
					pLastReplacableLesson = pOpenOpportunity;
				}
 
				if ( iInstanceCount >= pRootLesson->GetFixedInstancesMax() )
				{
					pLessonToReplace = pLastReplacableLesson;
					break;
				}
			}
		}
 
		if ( pLessonToReplace )
		{
			// Take the place of the previous instance
			if ( gameinstructor_verbose.GetInt() > 0 )
			{
				ConColorMsg( CBaseLesson::m_rgbaVerboseHeader, "GAME INSTRUCTOR: " );
				ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "Opportunity " );
				ConColorMsg( CBaseLesson::m_rgbaVerboseOpen, "\"%s\" ", pLesson->GetName() );
				ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "replacing open lesson of same type.\n" );
			}
 
			pLesson->TakePlaceOf( pLessonToReplace );
			CloseOpportunity( pLessonToReplace );
		}
		else if ( iInstanceCount >= pRootLesson->GetFixedInstancesMax() )
		{
			// Don't add another lesson of this type
			if ( gameinstructor_verbose.GetInt() > 0 )
			{
				ConColorMsg( CBaseLesson::m_rgbaVerboseHeader, "GAME INSTRUCTOR: " );
				ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "Opportunity " );
				ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\"%s\" ", pLesson->GetName() );
				ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "NOT opened (there is too many started lessons of this type).\n" );
			}
 
			delete pLesson;
			return false;
		}
	}
 
	if ( gameinstructor_verbose.GetInt() > 0 )
	{
		ConColorMsg( CBaseLesson::m_rgbaVerboseHeader, "GAME INSTRUCTOR: " );
		ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "Opportunity " );
		ConColorMsg( CBaseLesson::m_rgbaVerboseOpen, "\"%s\" ", pLesson->GetName() );
		ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "opened.\n" );
	}
 
	m_OpenOpportunities.AddToTail( pLesson );
 
	return true;
}
void Resolver::Resolve()
{
	for (int i = 1; i <= g_GlobalVars->maxClients; i++)
	{
		auto &record = arr_infos[i];
		if (!record.m_bActive)
			continue;

		C_BasePlayer *player = C_BasePlayer::GetPlayerByIndex(i);
		if (!player || !player->IsAlive() || player->IsDormant() || player == g_LocalPlayer)
			continue;

		if (record.m_flVelocity == 0.f && player->m_vecVelocity().Length2D() != 0.f)
		{
			Math::VectorAngles(player->m_vecVelocity(), record.m_angDirectionFirstMoving);
			record.m_nCorrectedFakewalkIdx = 0;
		}

		auto firedShots = g_LocalPlayer->m_iShotsFired();

		if (g_Options.debug_fliponkey)
		{
			float_t new_yaw = player->m_flLowerBodyYawTarget();
			if (g_InputSystem->IsButtonDown(g_Options.debug_flipkey))
				new_yaw += 180.f;
			new_yaw = Math::ClampYaw(new_yaw);
			player->m_angEyeAngles().yaw = new_yaw;
			return;
		}

		if (g_Options.hvh_resolver_override && g_InputSystem->IsButtonDown(g_Options.hvh_resolver_override_key))
		{
			Override(); //needs an improvement sometimes f****d up xD

			Global::resolverModes[player->EntIndex()] = "Overriding";

			return;
		}

		AnimationLayer curBalanceLayer, prevBalanceLayer;

		ResolveInfo curtickrecord;
		curtickrecord.SaveRecord(player);

		if ((player->m_fFlags() & FL_ONGROUND) && (IsFakewalking(player, curtickrecord) || (player->m_vecVelocity().Length2D() > 0.1f && player->m_vecVelocity().Length2D() < 45.f && !(player->m_fFlags() & FL_DUCKING)))) //Fakewalk, shiftwalk check // We have to rework the fakewalk resolving, it sucks :D
		{
			float_t new_yaw = ResolveFakewalk(player, curtickrecord);
			new_yaw = Math::ClampYaw(new_yaw);

			player->m_angEyeAngles().yaw = new_yaw;

			Global::resolverModes[player->EntIndex()] = "Fakewalking";

			continue;
		}
		if (IsEntityMoving(player))
		{
			float_t new_yaw = player->m_flLowerBodyYawTarget();
			new_yaw = Math::ClampYaw(new_yaw);

			player->m_angEyeAngles().yaw = new_yaw;

			record.m_flStandingTime = player->m_flSimulationTime();
			record.m_flMovingLBY = player->m_flLowerBodyYawTarget();
			record.m_bIsMoving = true;

			Global::resolverModes[player->EntIndex()] = "Moving";

			continue;
		}
		if (IsAdjustingBalance(player, curtickrecord, &curBalanceLayer))
		{
			if (fabsf(LBYDelta(curtickrecord)) > 35.f)
			{
				float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta;
				new_yaw = Math::ClampYaw(new_yaw);

				player->m_angEyeAngles().yaw = new_yaw;

				Global::resolverModes[player->EntIndex()] = "Fakehead (delta > 35)";
			}
			if (IsAdjustingBalance(player, record, &prevBalanceLayer))
			{
				if ((prevBalanceLayer.m_flCycle != curBalanceLayer.m_flCycle) || curBalanceLayer.m_flWeight == 1.f)
				{
					float
						flAnimTime = curBalanceLayer.m_flCycle,
						flSimTime = player->m_flSimulationTime();

					if (flAnimTime < 0.01f && prevBalanceLayer.m_flCycle > 0.01f && g_Options.rage_lagcompensation && CMBacktracking::Get().IsTickValid(TIME_TO_TICKS(flSimTime - flAnimTime)))
					{
						CMBacktracking::Get().SetOverwriteTick(player, QAngle(player->m_angEyeAngles().pitch, player->m_flLowerBodyYawTarget(), 0), (flSimTime - flAnimTime), 2);
					}

					float_t new_yaw = player->m_flLowerBodyYawTarget();
					new_yaw = Math::ClampYaw(new_yaw);

					player->m_angEyeAngles().yaw = new_yaw;

					Global::resolverModes[player->EntIndex()] = "Breaking LBY";

					continue;
				}
				else if (curBalanceLayer.m_flWeight == 0.f && (prevBalanceLayer.m_flCycle > 0.92f && curBalanceLayer.m_flCycle > 0.92f)) // breaking lby with delta < 120
				{
					if (player->m_flSimulationTime() >= record.m_flStandingTime + 0.22f && record.m_bIsMoving)
					{
						record.m_flLbyDelta = record.m_flLowerBodyYawTarget - player->m_flLowerBodyYawTarget();

						float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta;
						new_yaw = Math::ClampYaw(new_yaw);

						player->m_angEyeAngles().yaw = new_yaw;

						record.m_bIsMoving = false;

						Global::resolverModes[player->EntIndex()] = "Breaking LBY (delta < 120)";

						continue;
					}

					if (player->m_flSimulationTime() >= record.m_flStandingTime + 1.32f && std::fabsf(record.m_flLbyDelta) < 35.f)
					{
						record.m_flLbyDelta = record.m_flMovingLBY - player->m_flLowerBodyYawTarget();
						float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta;
						new_yaw = Math::ClampYaw(new_yaw);

						player->m_angEyeAngles().yaw = new_yaw;

						record.m_bIsMoving = false;

						Global::resolverModes[player->EntIndex()] = "LBY delta < 35";

						continue;
					}
				}
			}
			else
			{
				float_t new_yaw = player->m_flLowerBodyYawTarget();
				new_yaw = Math::ClampYaw(new_yaw);

				player->m_angEyeAngles().yaw = new_yaw;

				Global::resolverModes[player->EntIndex()] = "Other";

				continue;
			}
		}
		if (player->m_flSimulationTime() >= record.m_flStandingTime + 0.22f && record.m_bIsMoving)
		{
			record.m_flLbyDelta = record.m_flLowerBodyYawTarget - player->m_flLowerBodyYawTarget();

			float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta;
			new_yaw = Math::ClampYaw(new_yaw);

			player->m_angEyeAngles().yaw = new_yaw;

			record.m_bIsMoving = false;

			Global::resolverModes[player->EntIndex()] = "Breaking LBY (delta < 120)";

			continue;
		}
		if (player->m_flSimulationTime() >= record.m_flStandingTime + 1.32f && std::fabsf(record.m_flLbyDelta) < 35.f)
		{
			record.m_flLbyDelta = record.m_flMovingLBY - player->m_flLowerBodyYawTarget();
			float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta;
			new_yaw = Math::ClampYaw(new_yaw);

			player->m_angEyeAngles().yaw = new_yaw;

			record.m_bIsMoving = false;

			Global::resolverModes[player->EntIndex()] = "LBY delta < 35";

			continue;
		}

		float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta;
		new_yaw = Math::ClampYaw(new_yaw);

		player->m_angEyeAngles().yaw = new_yaw;
	}
}
//-----------------------------------------------------------------------------
// Purpose: Render current view into specified rectangle
// Input  : *rect - 
//-----------------------------------------------------------------------------
void CViewRender::Render( vrect_t *rect )
{
	/*static*/ std::vector<smCoord3f> view_head_pos;
	/*static*/ std::vector<smRotEuler> view_head_rot;

	static float learnt_x = 0.0;
	static float learnt_y = 0.0;
	static float learnt_z = fa_default_depth;
	static float learnt_xRot = fa_default_pitch;
	static float learnt_yRot = 0.0;
	static float learnt_zRot = 0.0;
	
	int i = 0;

	fa_fov_min = ( fov_desired.GetInt() + fov_fapi_window_adj_amount.GetInt() );

	Assert(s_DbgSetupOrigin == m_View.origin);
	Assert(s_DbgSetupAngles == m_View.angles);

	VPROF_BUDGET( "CViewRender::Render", "CViewRender::Render" );

	vrect_t vr = *rect;

	// Stub out the material system if necessary.
	CMatStubHandler matStub;

	bool drawViewModel;

	engine->EngineStats_BeginFrame();
	
	// Assume normal vis
	m_bForceNoVis			= false;
	
	
	C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();

	// IMPORTANT: Please acknowledge the author Torben Sko ([email protected], torbensko.com/software/head_tracking),
    // if you:

    // 1.1 Use or replicate any of the code pertaining to the utilisation of the head tracking data.
    // 1.2 Use any of the custom assets, including the modified crossbow and the human
    // character model.

	float aspectRatio = engine->GetScreenAspectRatio() * 0.75f;	 // / (4/3)
	
	if(pPlayer && pPlayer->IsAlive() && face_api.m_bFaceAPIHasCamera)
	{
		int head_pos_size = 0;
		if(!fa_paused)
		{
			// Warning: this code does not take parellel operations into account
			if(head_confidence > 0.0f)
			{	
				view_head_pos.push_back(latest_head_pos);
				view_head_rot.push_back(latest_head_rot);
			}

			// Restore to a neutral position on loss of the head by
			// scaling down the last recieved head position
			static float lost_time = 0.0f;
			if(fa_lost)
			{
				if(head_confidence == 0.0f && view_head_pos.size() > 0)
				{
					if(lost_time == 0.0f)
					{
						lost_time = engine->Time();
					}
					else if(engine->Time() > lost_time + fa_lost_pause)
					{
						smCoord3f previous_offset = view_head_pos.back();
						previous_offset.x *= fa_lost_scale;
						previous_offset.y *= fa_lost_scale;
						previous_offset.z = 
							((previous_offset.z - learnt_z) * fa_lost_scale) + learnt_z;
						
						smRotEuler previous_rotation = view_head_rot.back();
						previous_rotation.x_rads = 
							((previous_rotation.x_rads - learnt_xRot) * fa_lost_scale) + learnt_xRot;
						previous_rotation.y_rads *= fa_lost_scale;
						previous_rotation.z_rads *= fa_lost_scale;
						
						view_head_pos.push_back(previous_offset);
						view_head_rot.push_back(previous_rotation);
					}
				}
				else
				{
					if(lost_time > 0.0f)
					{
						/*char log[40];
						sprintf(log, "lost the head for %f seconds", engine->Time() - lost_time);
						record(log);*/

						lost_time = 0.0f;
					}
				}
			}

			// Use a while statement in case the user has decreased the 
			// smoothing rate since last time
			head_pos_size = view_head_pos.size();
			while( head_pos_size > fa_smoothing )
			{
				view_head_pos.erase(view_head_pos.begin());
				view_head_rot.erase(view_head_rot.begin());
			}
		}

		x = 0.0f;
		y = 0.0f;
		z = 0.0f;

		float xRot = 0.0f;
		float yRot = 0.0f;
		float zRot = 0.0f;

		// Compute the smoothed head movements
		head_pos_size = view_head_pos.size();
		if(head_pos_size > 0)
		{
			for(i = 0; i < head_pos_size; i++) 
			{
				x += view_head_pos[i].x;
				y += view_head_pos[i].y;
				z += view_head_pos[i].z;
				xRot += view_head_rot[i].x_rads;
				yRot += view_head_rot[i].y_rads;
				zRot += view_head_rot[i].z_rads;
			}

			x /= view_head_pos.size();
			y /= view_head_pos.size();
			z /= view_head_pos.size();
			xRot /= view_head_pos.size();
			yRot /= view_head_pos.size();
			zRot /= view_head_pos.size();
		}

		// Corrects the arching that occurs when moving towards the camera
		if(fa_arcCorrection)
			y += (z - fa_default_depth) * fa_arcCorrection_scale;
		
		// Show the head data
		//if(fa_show_preHeadData) DevMsg("   pre: pos\tx:%f\ty:%f\tz:%f\n        rot\tx:%f\ty:%f\tz:%f\n", x, y, z, xRot, yRot, zRot);
		
		// IMPORTANT: Please acknowledge the author Torben Sko ([email protected], torbensko.com/software/head_tracking),
        // if you:

        // 1.1 Use or replicate any of the code pertaining to the utilisation of the head tracking data.
        // 1.2 Use any of the custom assets, including the modified crossbow and the human
        // character model.
		
		// Learns the player's neutral position
		static bool reset_learning = false;
		if(!fa_learning)
		{
			if(reset_learning)
			{
				learnt_x = 0.0f;
				learnt_y = 0.0f;
				learnt_z = fa_default_depth;
				learnt_xRot = fa_default_pitch;
				learnt_yRot = 0.0f;
				learnt_zRot = 0.0f;

				reset_learning = true;
			}
		}
		else if(fa_learning && head_confidence > 0.0f && !fa_paused)
		{
			float diff, change;

			diff = learnt_x - x;
			(diff != 0.0f) ? change = (0.0000001 * fa_learning_influence) / diff : change = 0.0f;
			(fabs(change) < fabs(diff)) ? learnt_x -= change : learnt_x = x;
			x -= learnt_x;

			diff = learnt_y - y;
			(diff != 0.0f) ? change = (0.0000001 * fa_learning_influence) / diff : change = 0.0f;
			(fabs(change) < fabs(diff)) ? learnt_y -= change : learnt_y = y;
			y -= learnt_y;

			diff = learnt_z - z;
			(diff != 0.0f) ? change = (0.0000001 * fa_learning_influence) / diff : change = 0.0f;
			(fabs(change) < fabs(diff)) ? learnt_z -= change : learnt_z = z;
			z = fa_default_depth + (z - learnt_z);

			diff = learnt_xRot - xRot;
			(diff != 0.0f) ? change = (0.0000001 * fa_learning_influence) / diff : change = 0.0f;
			(fabs(change) < fabs(diff)) ? learnt_xRot -= change : learnt_xRot = xRot;
			xRot = fa_default_pitch + (xRot - learnt_xRot);

			diff = learnt_yRot - yRot;
			(diff != 0.0f) ? change = (0.0000001 * fa_learning_influence) / diff : change = 0.0f;
			(fabs(change) < fabs(diff)) ? learnt_yRot -= change : learnt_yRot = yRot;
			yRot -= learnt_yRot;

			diff = learnt_zRot - zRot;
			(diff != 0.0f) ? change = (0.0000001 * fa_learning_influence) / diff : change = 0.0f;
			(fabs(change) < fabs(diff)) ? learnt_zRot -= change : learnt_zRot = zRot;
			zRot -= learnt_zRot;

			reset_learning = true;
		}

		// IMPORTANT: Please acknowledge the author Torben Sko ([email protected], torbensko.com/software/head_tracking),
        // if you:

        // 1.1 Use or replicate any of the code pertaining to the utilisation of the head tracking data.
        // 1.2 Use any of the custom assets, including the modified crossbow and the human
        // character model.

		// Resets the tracker on low confidence
		static float reset_time = 0.0f;
		static float waiting_for_reset = 0.0f;
		if(fa_confidenceMinimum)
		{
			if(waiting_for_reset > 0.0f)
			{
				if(head_confidence > 0.0f)
				{
					/*char log[40];
					sprintf(log, "Reset FaceAPI engine and regained head after %f seconds", engine->Time() - waiting_for_reset);
					record(log);*/

					waiting_for_reset = 0.0f;
				}
			}
			else if(head_confidence < fa_confidenceMinimum_threshold && learnt_x <= fabs(fa_confidenceMinimum_widthRange) && learnt_zRot <= fabs(fa_confidenceMinimum_yollRange))
			{
				if(reset_time == 0.0f)
				{
					reset_time = engine->Time() + fa_confidenceMinimum_timeout;
				}
				else if(engine->Time() > reset_time)
				{
					//char logMsg[256];

					reset_time = 0.0f;
					face_api.reset();
					waiting_for_reset = engine->Time();

					// The learnt values were probably wrong, so reset them
					learnt_x = 0.0f;
					learnt_y = 0.0f;
					learnt_z = fa_default_depth;
					learnt_xRot = fa_default_pitch;
					learnt_yRot = 0.0f;
					learnt_zRot = 0.0f;

					/*sprintf(logMsg, 
						"confidence droped below %.2f%% for %.2f seconds, whilst (learnt) head.width <= |%.2f| and (learnt) head.roll <= |%.2f|", 
						fa_confidenceMinimum_threshold, 
						fa_confidenceMinimum_timeout, 
						fa_confidenceMinimum_widthRange, 
						fa_confidenceMinimum_yollRange);
					record(logMsg);*/
				}
			}
			else
			{
				reset_time = 0.0f;
			}
		}

		// IMPORTANT: Please acknowledge the author Torben Sko ([email protected], torbensko.com/software/head_tracking),
        // if you:

        // 1.1 Use or replicate any of the code pertaining to the utilisation of the head tracking data.
        // 1.2 Use any of the custom assets, including the modified crossbow and the human
        // character model.

		if(faceapi_mode.GetInt() > 1 && !engine->IsPaused())
		{
			// alters the fov based user's head position 
			float forward = fa_fov_depthScale * (z + fa_fov_depthOffset);
			float head_fov = fa_fov_min + (1 - fa_fov_influence) * default_fov.GetFloat() + fa_fov_influence * (2 * radToDeg(atan((fa_fov_screenWidth / 2) / (forward))));
			m_View.fov = ScaleFOVByWidthRatio( head_fov, aspectRatio );
			m_View.fovViewmodel = m_View.fov * fa_fov_modelViewScale;

			// rotate the camera based on the user's head offsets
			m_View.angles[YAW] += fa_camRotByHeadOff_globalScale * fa_camRotByHeadOff_yawScale * radToDeg(atan(x / z));
			m_View.angles[PITCH] += fa_camRotByHeadOff_globalScale * fa_camRotByHeadOff_pitchScale * radToDeg(atan(y / z));

			// offset the camera based on the user's head offsets
			float depth, height, width;
				
			depth = fa_camOffByHeadOff_depthScale * fa_camOffByHeadOff_globalScale * (z - fa_default_depth);
			m_View.origin.x -= depth * cos(degToRad(m_View.angles[YAW]));
			m_View.origin.y -= depth * sin(degToRad(m_View.angles[YAW]));
				
			width = fa_camOffByHeadOff_widthScale * fa_camOffByHeadOff_globalScale * x;
			m_View.origin.y -= width * cos(degToRad(m_View.angles[YAW]));
			m_View.origin.x += width * sin(degToRad(m_View.angles[YAW]));
				
			height = fa_camOffByHeadOff_heightScale * fa_camOffByHeadOff_globalScale * y;
			m_View.origin.z += height;
			
			// Alters the vanishing point based on the user's head offset
			offHor = -fa_vanish_depth * (x / z);
			offVert = -fa_vanish_depth * (y / z);

			m_View.m_bOffCenter = true;
			m_View.m_flOffCenterTop = 1.0f - offVert;
			m_View.m_flOffCenterBottom = 0.0f - offVert;
			m_View.m_flOffCenterLeft = 0.0f - offHor;
			m_View.m_flOffCenterRight = 1.0f - offHor;
		}
		else
		{
			m_View.fov = ScaleFOVByWidthRatio( m_View.fov,  aspectRatio );
			m_View.fovViewmodel = ScaleFOVByWidthRatio( m_View.fovViewmodel, aspectRatio );
			m_View.m_bOffCenter = false;
			offHor = 0.0f;
			offVert = 0.0f;
		}
		
		// Show the head data
		//if(fa_show_postHeadData) DevMsg("  post: pos\tx:%f\ty:%f\tz:%f\n        rot\tx:%f\ty:%f\tz:%f\n", x, y, z, xRot, yRot, zRot);

		// Show the learnt head data
		//if(fa_show_learntHeadData) DevMsg("learnt: pos\tx:%f\ty:%f\tz:%f\n        rot\tx:%f\ty:%f\tz:%f\n", learnt_x, learnt_y, learnt_z, learnt_xRot, learnt_yRot, learnt_zRot);

		// IMPORTANT: Please acknowledge the author Torben Sko ([email protected], torbensko.com/software/head_tracking),
        // if you:

        // 1.1 Use or replicate any of the code pertaining to the utilisation of the head tracking data.
        // 1.2 Use any of the custom assets, including the modified crossbow and the human
        // character model.

		if((faceapi_mode.GetInt() == 1 || faceapi_mode.GetInt() == 3) && !engine->IsPaused())
		{
			//float offPeer = 0.0f;
			float rollPeer = 0.0f;
			//float yawPeer = 0.0f;
			
			/*if(fa_peering_off)
				if(x > fa_peering_offStart)
					offPeer = (x - fa_peering_offStart) / (fa_peering_offEnd - fa_peering_offStart);
				else if(x < -fa_peering_offStart)
					offPeer = (x + fa_peering_offStart) / (fa_peering_offEnd - fa_peering_offStart);*/

			if(fa_peering_roll)
				if(zRot > fa_peering_rollStart)
					rollPeer = -(zRot - fa_peering_rollStart) / (fa_peering_rollEnd - fa_peering_rollStart);
				else if(zRot < -fa_peering_rollStart)
					rollPeer = -(zRot + fa_peering_rollStart) / (fa_peering_rollEnd - fa_peering_rollStart);
			
			/*if(fa_peering_yaw)
				if(yRot > fa_peering_yawStart)
					yawPeer = -(yRot - fa_peering_yawStart) / (fa_peering_yawEnd - fa_peering_yawStart);
				else if(yRot < -fa_peering_yawStart)
					yawPeer = -(yRot + fa_peering_yawStart) / (fa_peering_yawEnd - fa_peering_yawStart);*/

			float peer = /*offPeer + */rollPeer /*+ yawPeer*/;
			if(peer > 1.0f) peer = 1.0f;
			if(peer < -1.0f) peer = -1.0f;

			if(peer != 0.0f)
			{
				peer = pow(fabs(peer), fa_peering_ease) * (fabs(peer) / peer);
			
				QAngle angles = pPlayer->GetViewModel()->GetAbsAngles();
				angles[PITCH] += fabs(peer) * fa_peering_gunTilt;
				pPlayer->GetViewModel()->SetAbsAngles(angles);

				m_View.angles[ROLL] += peer * fa_peering_headTilt;

				Vector eyes, eye_offset;
				eyes = pPlayer->EyePosition();

				float hor_move = peer * fa_peering_size;
				eye_offset.y = -hor_move * cos(degToRad(m_View.angles[YAW]));
				eye_offset.x = hor_move * sin(degToRad(m_View.angles[YAW]));
				eye_offset.z = 0.0f;

				// Don't allow peering through walls
				trace_t tr;
				UTIL_TraceHull(eyes, eyes + eye_offset, PEER_HULL_MIN, PEER_HULL_MAX, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr);
				
				eye_offset.z = -fabs(peer) * fa_peering_headLower;
				m_View.origin += eye_offset * tr.fraction;

				static float peer_right = 0.0f;
				if(peer_right == 0.0f && peer == 1.0f)
				{
					peer_right = engine->Time();
				}
				else if(peer_right != 0.0f && peer != 1.0f)
				{
					/*char log[40];
					sprintf(log, "peered right for %f seconds", engine->Time() - peer_right);
					record(log);*/
					peer_right = 0.0f;
				}

				static float peer_left = 0.0f;
				if(peer_left == 0.0f && peer == -1.0f)
				{
					peer_left = engine->Time();
				}
				else if(peer_left != 0.0f && peer != -1.0f)
				{
					/*char log[40];
					sprintf(log, "peered left for %f seconds", engine->Time() - peer_left);
					record(log);*/
					peer_left = 0.0f;
				}
			}
		}
		
		// IMPORTANT: Please acknowledge the author Torben Sko ([email protected], torbensko.com/software/head_tracking),
        // if you:

        // 1.1 Use or replicate any of the code pertaining to the utilisation of the head tracking data.
        // 1.2 Use any of the custom assets, including the modified crossbow and the human
        // character model.


		rotate_x = 0.0f;
		rotate_y = 0.0f;
		if(fa_plyRotByHeadRot)
		{
			if(fabs(yRot) > fa_plyRotByHeadRot_yawMin)
			{
				float n_yRot = (fabs(yRot) - fa_plyRotByHeadRot_yawMin) / (fa_plyRotByHeadRot_yawMax - fa_plyRotByHeadRot_yawMin);
				if(n_yRot > 1.0f)
					n_yRot = 1.0f;
				if(n_yRot > 0.0f)
					n_yRot = pow(n_yRot, fa_plyRotByHeadRot_ease);
				rotate_x = n_yRot * fa_plyRotByHeadRot_yawSpeed * (yRot / fabs(yRot));
			}

			float off_xRot = xRot - learnt_xRot;
			if(fabs(off_xRot) > fa_plyRotByHeadRot_pitchMin)
			{
				float n_xRot = (fabs(off_xRot) - fa_plyRotByHeadRot_pitchMin) / (fa_plyRotByHeadRot_pitchMax - fa_plyRotByHeadRot_pitchMin);
				if(n_xRot > 1.0f)
					n_xRot = 1.0f;
				if(n_xRot > 0.0f)
					n_xRot = pow(n_xRot, fa_plyRotByHeadRot_ease);
				rotate_y = n_xRot * fa_plyRotByHeadRot_pitchSpeed * (off_xRot / fabs(off_xRot));
			}
		}
	}
	else
	{
		m_View.fov = ScaleFOVByWidthRatio( m_View.fov,  aspectRatio );
		m_View.fovViewmodel = ScaleFOVByWidthRatio( m_View.fovViewmodel, aspectRatio );
	}
	
	//m_View.fov = ScaleFOVByWidthRatio( m_View.fov,  aspectRatio );
	//m_View.fovViewmodel = ScaleFOVByWidthRatio( m_View.fovViewmodel, aspectRatio );
	
	// Let the client mode hook stuff.
	g_pClientMode->PreRender(&m_View);

	g_pClientMode->AdjustEngineViewport( vr.x, vr.y, vr.width, vr.height );

	ToolFramework_AdjustEngineViewport( vr.x, vr.y, vr.width, vr.height );

	float flViewportScale = mat_viewportscale.GetFloat();

	float engineAspectRatio = engine->GetScreenAspectRatio();

	m_View.x				= vr.x;
	m_View.y				= vr.y;
	m_View.width			= vr.width * flViewportScale;
	m_View.height			= vr.height * flViewportScale;
	m_View.m_flAspectRatio	= ( engineAspectRatio > 0.0f ) ? engineAspectRatio : ( (float)m_View.width / (float)m_View.height );

	int nClearFlags = VIEW_CLEAR_DEPTH | VIEW_CLEAR_STENCIL;

	if( gl_clear_randomcolor.GetBool() )
	{
		CMatRenderContextPtr pRenderContext( materials );
		pRenderContext->ClearColor3ub( rand()%256, rand()%256, rand()%256 );
		pRenderContext->ClearBuffers( true, false, false );
		pRenderContext->Release();
	}
	else if ( gl_clear.GetBool() )
	{
		nClearFlags |= VIEW_CLEAR_COLOR;
	}

	// Determine if we should draw view model ( client mode override )
	drawViewModel = g_pClientMode->ShouldDrawViewModel();

	if ( cl_leveloverview.GetFloat() > 0 )
	{
		SetUpOverView();		
		nClearFlags |= VIEW_CLEAR_COLOR;
		drawViewModel = false;
	}

	// Apply any player specific overrides
	//C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
	if ( pPlayer )
	{
		// Override view model if necessary
		if ( !pPlayer->m_Local.m_bDrawViewmodel )
		{
			drawViewModel = false;
		}
	}

	if(fa_weapon)
		drawViewModel = false;

	render->SetMainView( m_View.origin, m_View.angles );

	int flags = RENDERVIEW_DRAWHUD;
	if ( drawViewModel )
	{
		flags |= RENDERVIEW_DRAWVIEWMODEL;
	}
	RenderView( m_View, nClearFlags, flags );

	g_pClientMode->PostRender();

	engine->EngineStats_EndFrame();

#if !defined( _X360 )
	// Stop stubbing the material system so we can see the budget panel
	matStub.End();
#endif

	CViewSetup view2d;

	// Draw all of the UI stuff "fullscreen"
	view2d.x				= rect->x;
	view2d.y				= rect->y;
	view2d.width			= rect->width;
	view2d.height			= rect->height;
	render->Push2DView( view2d, 0, NULL, GetFrustum() );
	render->VGui_Paint( PAINT_UIPANELS );
	render->PopView( GetFrustum() );
}