Code/Vehicle/VehicleController.Camera.cs
using Sandbox;

namespace Meteor.VehicleTool.Vehicle;

public partial class VehicleController
{
	private float _cameraDistance = 100f;
	private float _eyez;

	[Property]
	[FeatureEnabled( "Camera", Icon = "videocam" )]
	public bool UseCameraControls { get; set; } = true;


	[Property]
	[Feature( "Camera" )]
	public bool ThirdPerson { get; set; } = true;

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

	/// <summary>
	/// The player's eye position, in first person mode
	/// </summary>
	[Property]
	[Feature( "Camera" )]
	public Vector3 EyePosition { get; set; }

	[Property]
	[Feature( "Camera" )]
	[InputAction]
	public string ToggleCameraModeButton { get; set; } = "view";

	/// <summary>
	/// The direction we're looking.
	/// </summary>
	[Sync( SyncFlags.Interpolate )]
	public Angles EyeAngles { get; set; }


	[Property]
	[Feature( "Camera" )]
	public float BodyHeight { get; set; } = 72f;

	[Property]
	[Feature( "Camera" )]
	public float EyeDistanceFromTop { get; set; } = 8f;

	private void UpdateCameraPosition()
	{
		CameraComponent cam = Scene.Camera;
		if ( cam == null )
			return;

		if ( !string.IsNullOrWhiteSpace( ToggleCameraModeButton ) && Input.Pressed( ToggleCameraModeButton ) )
		{
			ThirdPerson = !ThirdPerson;
			_cameraDistance = 20f;
		}
		float dt = Time.Delta / Scene.TimeScale;

		Rotation worldRotation = EyeAngles.ToRotation();

		cam.WorldRotation = worldRotation;
		Vector3 from = WorldPosition + Vector3.Up * (BodyHeight - EyeDistanceFromTop);
		if ( IsOnGround && _eyez != 0f )
		{
			from.z = _eyez.LerpTo( from.z, dt * 50f );
		}

		_eyez = from.z;

		if ( ThirdPerson )
		{
			Vector3 vector = worldRotation.Forward * (0f - CameraOffset.x) + worldRotation.Up * CameraOffset.z + worldRotation.Right * CameraOffset.y;
			SceneTrace trace = Scene.Trace;
			Vector3 to = from + vector;
			SceneTraceResult sceneTraceResult = trace.FromTo( in from, in to ).IgnoreGameObjectHierarchy( GameObject ).Radius( 8f ).Run();

			if ( sceneTraceResult.StartedSolid )
			{
				_cameraDistance = _cameraDistance.LerpTo( vector.Length, dt * 100f );
			}
			else if ( sceneTraceResult.Distance < _cameraDistance )
			{
				_cameraDistance = _cameraDistance.LerpTo( sceneTraceResult.Distance, dt * 200f );
			}
			else
			{
				_cameraDistance = _cameraDistance.LerpTo( sceneTraceResult.Distance, dt * 2f );
			}

			from += vector.Normal * _cameraDistance;
		}
		else
		{
			from = WorldTransform.PointToWorld( EyePosition );
		}

		cam.WorldPosition = from;

	}
}