using Sandbox; using Sandbox.Audio; using System; namespace VeloX; public partial class VeloXCar { public const float MIN_DRIFT_ANGLE = 10f; public const float MIN_DRIFT_SPEED = 10f; public const float MAX_DRIFT_ANGLE = 110f; public static readonly SoundFile SkidSound = SoundFile.Load( "sounds/tire/skid.wav" ); private SoundHandle _skidHandle; private float targetPitch; private float targetVolume; public float GetDriftAngle() { if ( !IsOnGround ) return 0; var velocity = Body.Velocity; var forward = WorldRotation.Forward; // Early exit if speed is too low if ( TotalSpeed < MIN_DRIFT_SPEED ) return 0f; // Normalize the dot product calculation float dotProduct = velocity.Normal.Dot( forward ); // Handle potential floating point precision issues float cosAngle = dotProduct; cosAngle = MathX.Clamp( cosAngle, -1f, 1f ); // Calculate angle in degrees float angle = MathF.Abs( MathX.RadianToDegree( MathF.Acos( cosAngle ) ) ); // Check if angle is within drift range if ( angle >= MIN_DRIFT_ANGLE && angle <= MAX_DRIFT_ANGLE ) return angle; return 0f; } protected virtual void UpdateDrift( float dt ) { var avgslip = 0f; foreach ( var item in Wheels ) avgslip += item.NormalizedLongitudinalSlip + item.NormalizedLateralSlip; float mul = Math.Clamp( avgslip, 0, 2 ); targetVolume = mul; targetPitch = 0.75f + 0.25f * mul; if ( mul > 0.1f && !_skidHandle.IsValid() ) { _skidHandle = Sound.PlayFile( SkidSound ); _skidHandle.TargetMixer = Mixer.Default; } if ( !_skidHandle.IsValid() ) return; _skidHandle.Pitch += (targetPitch - _skidHandle.Pitch) * dt * 5f; _skidHandle.Volume += (targetVolume - _skidHandle.Volume) * dt * 10f; _skidHandle.Position = WorldPosition; } }