Camera/JumperCamera.cs

public sealed class JumperCamera : Component
{
	//public CameraComponent CameraObject { get; set; }
	//[Property] public GameObject PlayerObject { get; set; }

	private Vector3 targetPosition;

	private float distance;
	public float ZoomLevel { get; set; } = 250f;
	public float MinDistance => 120.0f;
	public float MaxDistance => 350.0f;
	public float DistanceStep => 60.0f;

	protected override void OnPreRender()
	{
		if ( IsProxy )
			return;

		UpdateCamera();

		UpdateRenderAlpha();
	}


	void UpdateCamera()
	{
		var CameraObject = Scene.GetAllComponents<CameraComponent>().Where( x => x.IsMainCamera ).FirstOrDefault();

		if ( CameraObject is null ) return;

		if ( CameraObject.IsValid())
		{
			ZoomLevel += -Input.MouseWheel.y * RealTime.Delta * 1000.0f;
			ZoomLevel = ZoomLevel.Clamp( MinDistance, MaxDistance );

			var distanceA = distance.LerpInverse( MinDistance, MaxDistance );
			distance = distance.LerpTo( ZoomLevel, 5.0f * RealTime.Delta );
			targetPosition = Vector3.Lerp( targetPosition, GameObject.WorldPosition, 8.0f * RealTime.Delta );

			var pc = GameObject.Components.Get<PlayerController>( FindMode.EnabledInSelfAndChildren );
			if ( !pc.IsValid() ) return;
			var playerRotation = pc.EyeAngles.ToRotation();

			var height = 48.0f.LerpTo( 96.0f, distanceA );
			var center = targetPosition + Vector3.Up * height + playerRotation.Backward * 8.0f;
			var targetPos = center + playerRotation.Backward * ZoomLevel;

			var tr = Scene.PhysicsWorld.Trace.Ray( center, targetPos )
				.WithoutTags( "trigger", "player" )
				.Radius( 8.0f )
				.Run();

			if ( tr.Hit )
			{
				distance = Math.Min( distance, tr.Distance );
			}

			CameraObject.WorldPosition = center + playerRotation.Backward * distance;
			CameraObject.WorldRotation = playerRotation;
			CameraObject.WorldRotation *= Rotation.FromPitch( distanceA * 10.0f );
		}
	}
	public const float MaxRenderDistanceOther = 256.0f;
	public const float MaxRenderDistanceSelf = 200.0f;
	private void UpdateRenderAlpha()
	{
		var CameraObject = Scene.GetAllComponents<CameraComponent>().Where( x => x.IsMainCamera ).FirstOrDefault();

		var dist = CameraObject.WorldPosition.Distance( GameObject.WorldPosition );
		var a = 1.0f - dist.LerpInverse( MaxRenderDistanceSelf, MaxRenderDistanceSelf * 0.1f );
		a = Math.Max( a, .15f );
		a = Sandbox.Utility.Easing.EaseOut( a );

		var render = GameObject.Components.GetAll<SkinnedModelRenderer>( FindMode.EnabledInSelfAndDescendants );

		foreach ( var item in render )
		{
			item.Tint = item.Tint.WithAlpha( a );
		}
	}
}