LocalCameraControl.cs
using Sandbox;
using Sandbox.Diagnostics;

/// <summary>
/// Controls the camera that can be found in the local hierarchy rather than the global scene camera.
/// </summary>
[Icon( "videocam" )]
public sealed class LocalCameraControl : Component, IPlayerHealthEvent
{
	private CameraComponent cam;

	private PlayerController playerController;

	private float _cameraDistance = 100f;

	private float _eyez;

	private string _uniqueRenderExcludeTag;

	[Property]
	public bool UseCameraControls { get; set; } = true;


	[Property]
	public float EyeDistanceFromTop { get; set; } = 8f;


	[Property]
	public bool ThirdPerson { get; set; } = true;


	[Property]
	public bool HideBodyInFirstPerson { get; set; } = true;


	[Property]
	public bool RotateWithGround { get; set; } = true;


	[Property]
	public bool UseFovFromPreferences { get; set; } = true;


	[Property]
	public Vector3 CameraOffset { get; set; } = new Vector3( 256f, 0f, 12f );


	[Property]
	[InputAction]
	public string ToggleCameraModeButton { get; set; } = "view";

	public string ExcludeRenderTag => _uniqueRenderExcludeTag;

	protected override void OnEnabled()
	{
		base.OnEnabled();

		playerController = GetComponent<PlayerController>();
		Assert.IsValid( playerController );

		cam = GetComponentInChildren<CameraComponent>();
		Assert.IsValid( cam );

		_uniqueRenderExcludeTag = "viewer_" + GameObject.Id.ToString().Truncate( 4 );
	}

	public bool FollowBone = false;

	protected override void OnUpdate()
	{
		if ( !FollowBone )
		{
			UpdateCameraPosition();
			UpdateBodyVisibility();
		}
	}

	private void UpdateCameraPosition()
	{
		if ( !UseCameraControls )
		{
			return;
		}

		if ( !string.IsNullOrWhiteSpace( ToggleCameraModeButton ) && Input.Pressed( ToggleCameraModeButton ) )
		{
			ThirdPerson = !ThirdPerson;
			_cameraDistance = 20f;
		}

		Rotation worldRotation = playerController.EyeAngles.ToRotation();
		cam.WorldRotation = worldRotation;
		Vector3 from = base.WorldPosition + Vector3.Up * (playerController.BodyHeight - EyeDistanceFromTop);
		if ( playerController.IsOnGround && _eyez != 0f )
		{
			from.z = _eyez.LerpTo( from.z, Time.Delta * 50f );
		}

		_eyez = from.z;
		if ( !cam.RenderExcludeTags.Contains( _uniqueRenderExcludeTag ) )
		{
			cam.RenderExcludeTags.Add( _uniqueRenderExcludeTag );
		}

		if ( ThirdPerson )
		{
			Vector3 vector = worldRotation.Forward * (0f - CameraOffset.x) + worldRotation.Up * CameraOffset.z + worldRotation.Right * CameraOffset.y;
			SceneTrace trace = base.Scene.Trace;
			Vector3 to = from + vector;
			SceneTraceResult sceneTraceResult = trace.FromTo( in from, in to ).IgnoreGameObjectHierarchy( base.GameObject ).Radius( 8f )
				.Run();
			if ( sceneTraceResult.StartedSolid )
			{
				_cameraDistance = _cameraDistance.LerpTo( vector.Length, Time.Delta * 100f );
			}
			else if ( sceneTraceResult.Distance < _cameraDistance )
			{
				_cameraDistance = _cameraDistance.LerpTo( sceneTraceResult.Distance, Time.Delta * 200f );
			}
			else
			{
				_cameraDistance = _cameraDistance.LerpTo( sceneTraceResult.Distance, Time.Delta * 2f );
			}

			from += vector.Normal * _cameraDistance;
		}

		cam.WorldPosition = from;
		if ( UseFovFromPreferences )
		{
			cam.FieldOfView = Preferences.FieldOfView;
		}

		ISceneEvent<PlayerController.IEvents>.PostToGameObject( base.GameObject, delegate ( PlayerController.IEvents x )
		{
			x.PostCameraSetup( cam );
		} );
	}

	private void UpdateBodyVisibility()
	{
		if ( UseCameraControls && cam != null )
		{
			bool state = !ThirdPerson && HideBodyInFirstPerson && !base.IsProxy;
			if ( !base.IsProxy && _cameraDistance < 20f )
			{
				state = true;
			}

			if ( base.IsProxy )
			{
				state = false;
			}

			GameObject gameObject = playerController.Renderer?.GameObject ?? base.GameObject;
			if ( gameObject.IsValid() )
			{
				gameObject.Tags.Set( _uniqueRenderExcludeTag, state );
			}
		}
	}

	void IPlayerHealthEvent.OnDied( GameObject player )
	{
		if ( player != GameObject ) return;

		FollowBone = true;

		cam.GameObject.SetParent( GetComponentInChildren<ModelRenderer>().GetAttachmentObject( "eyes" ), false );
		cam.GameObject.LocalPosition = 0;
		cam.GameObject.LocalRotation = Rotation.Identity;

		TurnOffCameraOnDeath( player );
	}

	async void TurnOffCameraOnDeath( GameObject player )
	{
		await Task.DelayRealtimeSeconds( 2.0f );

		player.Enabled = false;
		Scene.GetComponentInChildren<PlayerReplicator>().AddViewport( cam.Viewport );

		IPlayerHealthEvent.Post( x => x.OnPostDeath( player ) );

		cam.DestroyGameObject();
		player.Destroy();
	}
}