ChickenControls.cs
using Sandbox;
using Sandbox.Citizen;
using Sandbox.Utility;
using Sandbox.VR;
using System;
using System.Diagnostics;
using System.Numerics;
using System.Runtime.CompilerServices;
using static Sandbox.ModelPhysics;
using static Sandbox.Sprite;

public sealed class ChickenControls : Component
{
	[Property] public Rigidbody controller { get; set; }
	[Property] public SkinnedModelRenderer model { get; set; }
	private Vector3 moveDirection = Vector3.Zero;

	[Property] public float gravity { get; set; } = 2f;
	[Property] public float jumpforce { get; set; } = 6f;
	[Property] public float dodgeforce { get; set; } = 6f;
	[Property] public float speed { get; set; } = 2f;
	[Property] public float timer { get; set; } = 0f;
	[Property] public float airtime { get; set; } = 0f;
	[Property] public float flyforce { get; set; } = 20f;
	[Property] public float flyspeed { get; set; } = 4f;
	[Property] public float dodgedir { get; set; } = 0f;

	[Property] public int tapCount { get; set; } = 0;

	[Property] public SoundEvent chickenrun { get; set; }
	[Property] public SoundEvent cluck { get; set; }
	[Property] public SoundEvent wingsflap { get; set; }
	[Property] public SoundEvent wingsfly { get; set; }
	[Property] public SoundEvent dodge { get; set; }

	[Property] public float TraceDistance { get; set; } = 2.0f;
	[Property] public float TraceRadius { get; set; } = 0.4f;

	[Property] public bool IsOnGround;

	[Property] public int cornpoints { get; set; }

	[Property] public TimeSince gametime { get; set; }
	[Property] public int timesave { get; set; }

	[Property] public AnimatedVelocityComponent chickenVel { get; set; }
	[Property] public SceneFile currentScene { get; set; }
	[Property] public int cornsave { get; set; }

	[Property] public int w1 { get; set; }
	[Property] public int t1 { get; set; }

	[Property] public int highscore { get; set; }
	[Property] public int besttime { get; set; }
	private bool _hasPlayed;
	private bool _Played;











	protected override void OnStart()
	{
		gametime = ScoreManager.CurrentTime;


	}
	protected override void OnUpdate()
	{


		int timeInt = (int)ScoreManager.BestTime;
		besttime = timeInt;
		highscore = ScoreManager.HighScore;
		int myInt = (int)gametime;
		timesave = myInt;
		cornpoints = ScoreManager.CurrentScore;
		ScoreManager.CurrentTime = gametime;
		w1 = ScoreManager.AllWM;
		t1 = ScoreManager.AllTofu;

		if ( ScoreManager.WMCount > 9 )
		{
			ScoreManager.AllWM = 1;
			Sandbox.Services.Achievements.Unlock( "found_all_watermelon" );
		}
		if ( ScoreManager.TofuCount > 9 )
		{
			ScoreManager.AllTofu = 1;
			Sandbox.Services.Achievements.Unlock( "found_all_tofu" );
		}
		if ( ScoreManager.WMCount > 10 )
		{
			ScoreManager.WMCount = 10;
		}
		if ( w1 == 1 )
		{
			ScoreManager.WMCount = 10;
		}
		if ( ScoreManager.TofuCount > 10 )
		{
			ScoreManager.TofuCount = 10;
		}
		if ( t1 == 1 )
		{
			ScoreManager.TofuCount = 10;
		}

	}
	protected override void OnFixedUpdate()
	{
		ProcessGroundMovement();
		ProcessGroundJump();
		ProcessFly();
		ProcessFlyMovement();
		ProcessDodge();

		moveDirection = controller.Velocity;
		var startPos = Transform.Position + Vector3.Up * 0.1f;
		var endPos = startPos + Vector3.Down * TraceDistance;

		// Perform a sphere/capsule trace to check for solid objects
		var tr = Scene.Trace.Sphere( TraceRadius, startPos, endPos )
			.IgnoreGameObject( GameObject ) // Don't hit the player
			.Run();

		// If the trace hit anything solid, we are grounded
		IsOnGround = tr.Hit;

	}








	void ProcessGroundMovement()
	{
		float horizontalInput = Input.AnalogMove.y;


		if ( IsOnGround && Input.Down( "Right" ) && (timer < 1) || (IsOnGround && horizontalInput < -0.5f) && (timer < 1) )
		{
			MoveRight();
			if ( IsOnGround && Input.Pressed( "Run" ) )
			{
				Dodge();
			}
		}
		else if ( IsOnGround && !Input.Pressed( "Right" ) && !Input.Pressed( "Left" ) && !Input.Down( "Run" ) && !Input.Down( "Jump" ) && horizontalInput == 0 )
		{
			StopFlying();
		}
		if ( IsOnGround && Input.Down( "Left" ) && (timer < 1) || (IsOnGround && horizontalInput > 0.5f) && (timer < 1) )
		{
			MoveLeft();
		}
		if ( IsOnGround && Input.Pressed( "Right" ) )
		{
			GameObject.PlaySound( chickenrun );
		}
		if ( Input.Released( "Right" ) )
		{
			GameObject.StopAllSounds();
		}
		if ( IsOnGround && Input.Pressed( "Left" ) )
		{
			GameObject.PlaySound( chickenrun );
		}
		if ( Input.Released( "Left" ) )
		{
			GameObject.StopAllSounds();
		}
		if ( IsOnGround && horizontalInput < -0.5f )
		{

			if ( !_hasPlayed )
			{
				// Play the sound once from the object's position
				GameObject.PlaySound( chickenrun );
				_hasPlayed = true;
			}
		}
		else
		{
			// Reset the flag once the joystick returns to center
			_hasPlayed = false;
		}
		if ( IsOnGround && horizontalInput > 0.5f )
		{

			if ( !_Played )
			{
				// Play the sound once from the object's position
				GameObject.PlaySound( chickenrun );
				_Played = true;
			}
		}
		else
		{
			// Reset the flag once the joystick returns to center
			_Played = false;
		}
		if ( IsOnGround && horizontalInput == 0f && !Input.Down( "Jump" ) && !Input.Down( "Run" ) )
		{
			GameObject.StopAllSounds();
		}



	}
	void ProcessDodge()
	{
		if ( IsOnGround && Input.Pressed( "Run" ) )
		{
			Dodge();
		}

	}
	void ProcessGroundJump()
	{


		if ( IsOnGround && Input.Pressed( "Jump" ) && (timer < 1) )
		{
			Jump();
		}


		if ( Input.Pressed( "Jump" ) )
		{
			tapCount += 1;
		}
		if ( Input.Released( "Jump" ) )
		{
			timer = 0;
		}
		if ( Input.Released( "Run" ) )
		{
			timer = 0;
		}
		if ( !IsOnGround )
		{
			airtime += Time.Delta;
		}
			if ( IsOnGround )
		{
			tapCount = 0;
			airtime = 0;
		}

	}

	void ProcessFly()
	{
		if ( (tapCount > 0) && (tapCount < 2) && Input.Pressed( "Jump" ) && !IsOnGround )
		{
			DoubleJump();
			airtime = 0;
		}
		if ( (tapCount > 1) && (tapCount < 3) && Input.Pressed( "Jump" ) && !IsOnGround )
		{
			TripleJump();
			airtime = 0;
		}



	}
	void ProcessFlyMovement()
	{
		float horizontalInput = Input.AnalogMove.y;
		if ( !IsOnGround && Input.Down( "Right" ) && !Input.Pressed( "Jump" ) || (!IsOnGround && horizontalInput < -0.5f) && !Input.Pressed( "Jump" ) )
		{
			FlyRight();
		}
		if ( !IsOnGround && Input.Down( "Left" ) && !Input.Pressed( "Jump" ) || (!IsOnGround && horizontalInput > 0.5f) && !Input.Pressed( "Jump" ) )
		{
			FlyLeft();
		}
		if ( !IsOnGround && !Input.Pressed( "Jump" ) && !Input.Pressed( "Run" ) && (airtime > 1.2f) )
		{
			FlyIdle();

		}





	}
	void MoveRight()
	{
		model.Set( "AnimPar", 1 );
		controller.Velocity = (Vector3.Backward * speed) + chickenVel.CurrentVelocity;
		LocalRotation = Rotation.From( 0f, 0f, 0f );
		Rotation.FromYaw( 0 );
		dodgedir = 0;
		if ( Input.Pressed( "Jump" ) )
		{
			model.Set( "AnimPar", 2 );
		}


	}
	void MoveLeft()
	{
		model.Set( "AnimPar", 1 );
		controller.Velocity = (Vector3.Forward * speed) + chickenVel.CurrentVelocity;
		LocalRotation = Rotation.From( 0f, 180f, 0f );
		Rotation.FromYaw( 180 );
		dodgedir = 1;
		if ( Input.Pressed( "Jump" ) )
		{
			model.Set( "AnimPar", 2 );
		}


	}


	void Dodge()
	{
		model.Set( "AnimPar", 5 );
		controller.Velocity = 0;
		timer += Time.Delta * 100;
		if ( dodgedir == 0 )
		{
			controller.ApplyImpulse( (Vector3.Up * dodgeforce) + chickenVel.CurrentVelocity );
			controller.ApplyImpulse( (Vector3.Forward * dodgeforce) + chickenVel.CurrentVelocity );
		}
		if ( dodgedir == 1 )
		{
			controller.ApplyImpulse( (Vector3.Up * dodgeforce) + chickenVel.CurrentVelocity );
			controller.ApplyImpulse( (Vector3.Backward * dodgeforce) + chickenVel.CurrentVelocity );
		}

		GameObject.PlaySound( dodge );
	}

	void Jump()
	{
		GameObject.StopAllSounds();
		model.Set( "AnimPar", 2 );
		controller.ApplyImpulse( (Vector3.Up * jumpforce) + chickenVel.CurrentVelocity );
		timer += Time.Delta * 100;
		GameObject.PlaySound( wingsflap );
		if ( (tapCount > 0) && (tapCount == 1) )
		{
			GameObject.PlaySound( wingsfly );
		}
	}
	void TripleJump()
	{
		model.Set( "AnimPar", 4 );
		controller.ApplyImpulse( Vector3.Up * flyforce );
		GameObject.PlaySound( cluck );
	}
	void DoubleJump()
	{
		model.Set( "AnimPar", 4 );
		controller.ApplyImpulse( Vector3.Up * flyforce );
		GameObject.PlaySound( wingsfly );
		if ( tapCount > 1 )
		{
			GameObject.PlaySound( cluck );
		}
	}
	void StopFlying()
	{
		model.Set( "AnimPar", 0 );
	}
	void FlyIdle()
	{
		model.Set( "AnimPar", 3 );

	}
	void FlyLeft()
	{

		controller.ApplyImpulse( Vector3.Forward * flyspeed );
		Transform.LocalRotation = Rotation.From( 0f, 180f, 0f );
		Rotation.FromYaw( 180 );

		dodgedir = 1;
	}
	void FlyRight()
	{

		controller.ApplyImpulse( Vector3.Backward * flyspeed );
		Transform.LocalRotation = Rotation.From( 0f, 0f, 0f );
		Rotation.FromYaw( 0 );

		dodgedir = 0;
	}
	public void Addcornpoints( int cornAmount )
	{
		ScoreManager.CurrentScore += cornAmount;

	}
	public string GetTimeString()
	{
		var time = gametime;
		var minutes = (int)time / 60;
		var seconds = (int)time % 60;
		return $"{minutes:00}:{seconds:00}";
	}
	public void LoadPlayerInfo()
	{
		var data = SaveLoadSystem.LoadGame();
		timesave = data.timesave;
		cornsave = data.cornsave;
		var options = new SceneLoadOptions();
		options.SetScene( data.currentScene );
		Scene.Load( options );
		ScoreManager.AllWM = data.w1;
		ScoreManager.AllTofu = data.t1;
		ScoreManager.HighScore = data.highscore;
		ScoreManager.BestTime = data.besttime;
	}

}
public struct PlayerSaveData
{
	[Property] public int timesave { get; set; }
	[Property] public int cornsave { get; set; }
	[Property] public SceneFile currentScene { get; set; }
	[Property] public int w1 { get; set; }
	[Property] public int t1 { get; set; }
	[Property] public int highscore { get; set; }
	[Property] public int besttime { get; set; }
}