SantaPlayerSled.cs
using Sandbox;
using System;
using System.Text.Json.Nodes;
using static Sandbox.Component;

public sealed class SantaPlayerSled : Component, ITriggerListener
{

	[Property]
	[Category( "Components" )]
	public SkinnedModelRenderer ModelRenderer { get; set; }

	[Property]
	[Category( "Components" )]
	public ModelRenderer Sleigh { get; set; }

	[Property]
	[Category( "Components" )]
	public GameObject Pivot { get; set; }

	[Property]
	[Category( "Components" )]
	public BoxCollider Collider { get; set; }

	[Property]
	[Category( "Components" )]
	public SoundPointComponent SkiingSound { get; set; }

	[Property]
	[Category( "Components" )]
	public ParticleConeEmitter SnowParticles { get; set; }

	[Property]
	[Category( "Particles" )]
	public GameObject SnowImpartParticle { get; set; }

	[Property]
	[Category( "Particles" )]
	public GameObject SmallSnowImpartParticle { get; set; }

	[Property]
	[Category( "Particles" )]
	public GameObject SmallerSnowImpartParticle { get; set; }

	[Property]
	[Category( "Particles" )]
	public GameObject GiftCollectParticle { get; set; }


	[Property]
	public float MaxTurnSpeed { get; set; } = 400f;

	public bool Alive = true;
	public float Velocity = 0f;
	public float Height = 0f;
	public bool CanJump => Pivot.LocalPosition.z <= 0f;

	private float _targetPitch = 0f;
	private float _originalTurnSpeed;
	private float _wishTurningVolume = 1f;

	protected override void OnStart()
	{
		_originalTurnSpeed = MaxTurnSpeed;
	}

	protected override void OnFixedUpdate()
	{
		if ( !Alive )
		{
			SkiingSound.Volume = 0f;
			return;
		}

		MaxTurnSpeed += Time.Delta * 5;
		var roadWidth = ChristmassyGameLogic.Instance.RoadWidth / (Pivot.LocalPosition.z > 0f ? 0.5f : 1.5f);
		var inputs = Input.AnalogMove;
		Velocity = MathX.Lerp( Velocity, inputs.y * MaxTurnSpeed, Time.Delta * (inputs.y == 0 ? 2f : 1f) );
		Velocity = MathX.Clamp( Velocity, -MaxTurnSpeed, MaxTurnSpeed );
		WorldPosition = WorldPosition.WithY( MathX.Clamp( WorldPosition.y + Velocity * Time.Delta, -roadWidth, roadWidth ) );

		SnowParticles.Rate = MathX.Remap( MathF.Abs( Velocity ), 0f, 1000f, 400f, 2000f );
		_wishTurningVolume = MathX.Remap( MathF.Abs( Velocity ), 0f, 800f, 0.2f, 3f );

		if ( CanJump && (WorldPosition.y <= -roadWidth || WorldPosition.y >= roadWidth) )
		{
			Velocity *= -0.25f;

			if ( Math.Abs( Velocity ) >= 10f )
				Sound.Play( "impact", WorldPosition )
					.Volume *= Math.Abs( Velocity ) / 500f;
		}

		if ( Pivot.LocalPosition.z > 0f || Height > 0f )
		{
			Pivot.LocalPosition += Vector3.Up * Time.Delta * Height;
			Pivot.LocalPosition = Pivot.LocalPosition.WithZ( MathF.Max( Pivot.LocalPosition.z, 0f ) );

			Collider.Center = Pivot.LocalPosition + Vector3.Up * 35f;
			Height -= Time.Delta * 1000f;

			_wishTurningVolume = 0f;
			SnowParticles.Enabled = false;
		}

		if ( CanJump && Height < 0f )
		{
			Collider.Center = Pivot.LocalPosition + Vector3.Up * 35f;
			Height = 0f;
			_targetPitch = 0f;

			if ( WorldPosition.y <= -roadWidth / 2.5f || WorldPosition.y >= roadWidth / 2.5f )
				Ragdoll();

			if ( _wishTurningVolume == 0f )
				_wishTurningVolume = 5f;

			if ( Alive )
				SnowParticles.Enabled = true;

			var impactRotation = WorldRotation * Rotation.FromPitch( -130f );
			var impact = SmallSnowImpartParticle?.Clone( WorldPosition, impactRotation );
		}

		if ( Input.Pressed( "jump" ) && CanJump && Pivot.IsValid() )
		{
			Height += 350f;
			_targetPitch = -30f;
			_wishTurningVolume = 3f;

			var impactRotation = WorldRotation * Rotation.FromPitch( -130f );
			var impact = SmallerSnowImpartParticle?.Clone( WorldPosition, impactRotation );
		}

		SkiingSound.SoundOverride = true;
		SkiingSound.Volume = MathX.Lerp( SkiingSound.Volume, _wishTurningVolume, Time.Delta * 10f );
		SkiingSound.Pitch = MathX.Remap( SkiingSound.Volume, 0f, 3f, 0.7f, 1.3f );

		var targetRotation = Rotation.FromPitch( _targetPitch ) * Rotation.FromYaw( Velocity / 10f );
		Pivot.LocalRotation = Rotation.Lerp( Pivot.LocalRotation, targetRotation, Time.Delta * 20f );

		// Animations
		if ( !ModelRenderer.IsValid() ) return;

		ModelRenderer.Set( "wish_y", inputs.y * -MaxTurnSpeed );
	}

	private GameObject _oldSanta;
	private GameObject _oldSleigh;

	[Button]
	public void Ragdoll()
	{
		if ( _oldSanta.IsValid() ) return;
		if ( !ModelRenderer.IsValid() ) return;

		Sound.Play( "impact", WorldPosition );

		var santa = ModelRenderer.GameObject;
		_oldSanta = santa.Clone( santa.WorldPosition, santa.WorldRotation, santa.WorldScale );
		_oldSanta.Tags.Remove( "player" );
		var ragdollRenderer = _oldSanta.GetComponent<SkinnedModelRenderer>();

		foreach ( var child in _oldSanta.Children )
			child.Flags &= ~GameObjectFlags.ProceduralBone;

		var santaPhysics = _oldSanta.AddComponent<ModelPhysics>();
		santaPhysics.Renderer = ragdollRenderer;
		santaPhysics.Model = ragdollRenderer.Model;

		SnowParticles.Enabled = false;
		var sleigh = Sleigh.GameObject;
		_oldSleigh = sleigh.Clone( sleigh.WorldPosition, sleigh.WorldRotation, sleigh.WorldScale );
		_oldSleigh.Tags.Remove( "player" );
		_oldSleigh.GetComponentInChildren<ParticleConeEmitter>()?.Destroy();
		var sleighRigidBody = _oldSleigh.AddComponent<Rigidbody>();
		sleighRigidBody.Velocity += Vector3.Up * 1000f + Vector3.Backward * 500f + Vector3.Left * Velocity;

		santa.Enabled = false;
		sleigh.Enabled = false;
		Collider.Enabled = false;

		var impactRotation = WorldRotation * Rotation.FromPitch( -130f );
		var impact = SnowImpartParticle?.Clone( WorldPosition, impactRotation );

		ChristmassyGameLogic.Instance.EndGame();
		Alive = false;
	}

	[Button]
	public void Unragdoll()
	{
		if ( !_oldSanta.IsValid() ) return;
		if ( !ModelRenderer.IsValid() ) return;

		_oldSanta.Destroy();
		_oldSleigh.Destroy();

		ModelRenderer.GameObject.Enabled = true;
		WorldPosition = WorldPosition.WithY( 0f );
		Sleigh.GameObject.Enabled = true;
		Collider.Enabled = true;
		MaxTurnSpeed = _originalTurnSpeed;
		Height = 0f;
		Velocity = 0f;
		SnowParticles.Enabled = true;

		Alive = true;
	}

	public void OnTriggerEnter( Collider other )
	{
		if ( other.Tags.Has( "gift" ) )
		{
			UnwrapGift( other.GameObject );
		}

		if ( other.Tags.Has( "obstacle" ) )
			Ragdoll();
	}

	private async void UnwrapGift( GameObject gift )
	{
		// Sound.Play( new SoundEvent( "sounds/gift.sound" ), WorldPosition ).Volume = 10f; // THIS DOES NOT WORK
		GiftCollectParticle?.Clone( gift.WorldPosition );
		Sound.Play( "gift", WorldPosition );

		ChristmassyGameLogic.Instance.Points += 10;
		Sandbox.Services.Stats.SetValue( "points", ChristmassyGameLogic.Instance.Points );

		TimeUntil animationEnd = 0.3f;
		var renderer = gift.GetComponent<ModelRenderer>();

		while ( !animationEnd )
		{
			gift.WorldPosition += Vector3.Up * Time.Delta * 400f;
			renderer.Tint = Color.White.WithAlpha( 1f - animationEnd.Fraction );

			await Task.FrameEnd();
		}

		gift.Enabled = false;
	}
}