diff --git a/Assets/sounds/tire/skid.wav.meta b/Assets/sounds/tire/skid.wav.meta new file mode 100644 index 0000000..cf1fcef --- /dev/null +++ b/Assets/sounds/tire/skid.wav.meta @@ -0,0 +1,8 @@ +{ + "loop": false, + "start": 0, + "end": 0, + "rate": 44100, + "compress": false, + "bitrate": 256 +} \ No newline at end of file diff --git a/Code/Base/Powertrain/Transmission.cs b/Code/Base/Powertrain/Transmission.cs index 6b1da8d..1ca2b47 100644 --- a/Code/Base/Powertrain/Transmission.cs +++ b/Code/Base/Powertrain/Transmission.cs @@ -15,7 +15,7 @@ public class Transmission : PowertrainComponent /// /// A class representing a single ground surface type. /// - public partial class TransmissionGearingProfile + public class TransmissionGearingProfile { /// /// List of forward gear ratios starting from 1st forward gear. diff --git a/Code/Base/VeloXBase.Input.cs b/Code/Base/VeloXBase.Input.cs index 1b1257f..72882f8 100644 --- a/Code/Base/VeloXBase.Input.cs +++ b/Code/Base/VeloXBase.Input.cs @@ -4,8 +4,10 @@ namespace VeloX; public abstract partial class VeloXBase { - internal InputResolver Input { get; set; } = new(); - public Connection Driver { get => Input.Driver; set => Input.Driver = value; } + internal readonly InputResolver Input = new(); + + public Guid DriverId { get; set; } + public Connection Driver => Connection.Find( DriverId ); public bool IsDriver => Connection.Local == Driver; private bool IsDriverActive => Driver is not null; @@ -109,18 +111,25 @@ public abstract partial class VeloXBase protected void UpdateInput() { //VerticalInput = Input.AnalogMove.x; + if ( IsDriverActive ) + { - Brakes = Input.Brake; - Throttle = Input.Throttle; + Brakes = Input.Brake; + Throttle = Input.Throttle; - Handbrake = Input.Down( "Handbrake" ) ? 1 : 0; + Handbrake = Input.Down( "Handbrake" ) ? 1 : 0; - SteeringAngle = Input.AnalogMove.y; + SteeringAngle = Input.AnalogMove.y; - IsClutching = Input.Down( "Clutch" ) ? 1 : 0; + IsClutching = Input.Down( "Clutch" ) ? 1 : 0; - IsShiftingUp = Input.Pressed( "Shift Up" ); - IsShiftingDown = Input.Pressed( "Shift Down" ); + IsShiftingUp = Input.Pressed( "Shift Up" ); + IsShiftingDown = Input.Pressed( "Shift Down" ); + } + else + { + ResetInput(); + } if ( TotalSpeed < 150 && Driver is null ) Handbrake = 1; diff --git a/Code/Base/VeloXBase.Phys.cs b/Code/Base/VeloXBase.Phys.cs index 1b7aef2..931e717 100644 --- a/Code/Base/VeloXBase.Phys.cs +++ b/Code/Base/VeloXBase.Phys.cs @@ -5,7 +5,6 @@ namespace VeloX; public abstract partial class VeloXBase { - private Vector3 linForce; private Vector3 angForce; protected const float BrakeForce = 4500f; protected const float HandbrakeForce = 35000f; @@ -13,18 +12,16 @@ public abstract partial class VeloXBase { if ( Body.Sleeping && Input.AnalogMove.x == 0 ) return; + //Body.PhysicsBody.SetInertiaTensor( new Vector3( 800000, 3000000, 6000000 ), Rotation.Identity ); var drag = AngularDrag; var mass = Body.Mass; var angVel = Body.AngularVelocity; - linForce.x = 0; - linForce.y = 0; - linForce.z = 0; - angForce = angForce.WithX( angVel.x * drag.x * mass * 1000 ); angForce = angForce.WithY( angVel.y * drag.y * mass * 1000 ); angForce = angForce.WithZ( angVel.z * drag.z * mass * 1000 ); + if ( Wheels.Count > 0 ) { Vector3 vehVel = Body.Velocity; @@ -58,8 +55,8 @@ public abstract partial class VeloXBase Body.AngularVelocity = vehAngVel; } - Body.ApplyForce( linForce ); - Body.ApplyTorque( angForce ); + //Body.ApplyForce( linForce ); + //Body.ApplyTorque( angForce ); } diff --git a/Code/Base/VeloXBase.cs b/Code/Base/VeloXBase.cs index b823bef..9ff86f9 100644 --- a/Code/Base/VeloXBase.cs +++ b/Code/Base/VeloXBase.cs @@ -56,10 +56,4 @@ public abstract partial class VeloXBase : Component, IGameObjectNetworkEvents PhysicsSimulate(); } - //void IGameObjectNetworkEvents.NetworkOwnerChanged( Connection newOwner, Connection previousOwner ) - //{ - - // Driver = newOwner; - // EngineIgnition = Driver is not null; - //} } diff --git a/Code/Base/Wheel/WheelManager.cs b/Code/Base/Wheel/WheelManager.cs index 80d8722..49fd02d 100644 --- a/Code/Base/Wheel/WheelManager.cs +++ b/Code/Base/Wheel/WheelManager.cs @@ -8,6 +8,9 @@ internal sealed class WheelManager : GameObjectSystem public WheelManager( Scene scene ) : base( scene ) { + if ( Application.IsDedicatedServer ) + return; + Listen( Stage.StartFixedUpdate, -99, UpdateWheels, "UpdateWheels" ); Listen( Stage.StartFixedUpdate, -100, UpdateEngine, "UpdateEngine" ); } diff --git a/Code/Car/VeloXCar.ABS.cs b/Code/Car/VeloXCar.ABS.cs index dbfb9dc..6a42691 100644 --- a/Code/Car/VeloXCar.ABS.cs +++ b/Code/Car/VeloXCar.ABS.cs @@ -15,7 +15,7 @@ public partial class VeloXCar if ( !UseABS ) return; - if ( TotalSpeed < 100 || Steering.AlmostEqual( 0, 1 ) ) + if ( TotalSpeed < 100 || SteeringAngle.AlmostEqual( 0, 1 ) ) return; diff --git a/Code/Car/VeloXCar.Drift.cs b/Code/Car/VeloXCar.Drift.cs index 16b3c27..abae15e 100644 --- a/Code/Car/VeloXCar.Drift.cs +++ b/Code/Car/VeloXCar.Drift.cs @@ -1,6 +1,7 @@  using Sandbox; +using Sandbox.Audio; using System; namespace VeloX; @@ -48,23 +49,27 @@ public partial class VeloXCar protected virtual void UpdateDrift( float dt ) { - float driftAngle = GetDriftAngle(); - float mul = (driftAngle - MIN_DRIFT_ANGLE) / (90 - MIN_DRIFT_ANGLE); + var avgslip = 0f; + foreach ( var item in Wheels ) + avgslip += item.NormalizedLongitudinalSlip + item.NormalizedLateralSlip; - if ( !_skidHandle.IsValid() ) - _skidHandle = Sound.PlayFile( SkidSound ); - - if ( !_skidHandle.IsValid() ) - return; + 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; - - } } diff --git a/Code/Car/VeloXCar.ESC.cs b/Code/Car/VeloXCar.ESC.cs index a06640a..07e33c4 100644 --- a/Code/Car/VeloXCar.ESC.cs +++ b/Code/Car/VeloXCar.ESC.cs @@ -24,15 +24,6 @@ public partial class VeloXCar angle -= SteerAngle.yaw * 0.5f; float absAngle = angle < 0 ? -angle : angle; - //foreach ( var wheel in Wheels ) - //{ - // if ( !wheel.IsOnGround ) - // continue; - // Log.Info( wheel.LongitudinalSlip < 0.1f ); - // if ( wheel.LongitudinalSlip < 0.1f ) - // wheel.BrakeTorque += Math.Abs( wheel.LongitudinalSlip ) * 10000; - //} - if ( Engine.RevLimiterActive || absAngle < 2f ) return; diff --git a/Code/Car/VeloXCar.Steering.cs b/Code/Car/VeloXCar.Steering.cs index 602fefa..e53f956 100644 --- a/Code/Car/VeloXCar.Steering.cs +++ b/Code/Car/VeloXCar.Steering.cs @@ -21,16 +21,11 @@ public partial class VeloXCar public int CarDirection { get { return ForwardSpeed < 1 ? 0 : (VelocityAngle < 90 && VelocityAngle > -90 ? 1 : -1); } } public float VelocityAngle { get; private set; } - [Sync] public float Steering { get; private set; } private float currentSteerAngle; - private float inputSteer; private void UpdateSteering( float dt ) { - inputSteer = Input.AnalogMove.y; - - - float targetSteerAngle = inputSteer * MaxSteerAngle; + float targetSteerAngle = SteeringAngle * MaxSteerAngle; if ( !Input.Down( "Jump" ) ) targetSteerAngle *= Math.Clamp( 1 - Math.Clamp( TotalSpeed / 3000, 0f, 0.85f ), -1, 1 ); @@ -42,10 +37,9 @@ public partial class VeloXCar if ( TotalSpeed > 150 && CarDirection > 0 && IsOnGround ) targetAngle = VelocityAngle * MaxSteerAngleMultiplier; - float lerpSpeed = Math.Abs( inputSteer ) < 0.1f ? SteerReturnSpeed : SteerInputResponse; + float lerpSpeed = Math.Abs( SteeringAngle ) < 0.1f ? SteerReturnSpeed : SteerInputResponse; currentSteerAngle = ExpDecay( currentSteerAngle, targetSteerAngle, lerpSpeed, Time.Delta ); - Steering = currentSteerAngle + targetAngle; - SteerAngle = new( 0, Math.Clamp( Steering, -MaxSteerAngle, MaxSteerAngle ), 0 ); + SteerAngle = new( 0, Math.Clamp( currentSteerAngle + targetAngle, -MaxSteerAngle, MaxSteerAngle ), 0 ); } } diff --git a/Code/Car/VeloXCar.TCS.cs b/Code/Car/VeloXCar.TCS.cs new file mode 100644 index 0000000..5cd9340 --- /dev/null +++ b/Code/Car/VeloXCar.TCS.cs @@ -0,0 +1,39 @@ +using Sandbox; +using System; + +namespace VeloX; + + +public partial class VeloXCar +{ + public bool TCSActive { get; private set; } = true; + public static bool UseTCS = true; + + private void UpdateTCS() + { + TCSActive = false; + + if ( !UseTCS ) + return; + + if ( TotalSpeed < 50 || CarDirection != 1 ) + return; + + float vehicleSpeed = TotalSpeed.InchToMeter(); + + foreach ( var wheel in Wheels ) + { + if ( !wheel.IsOnGround ) + continue; + + float wheelLinearSpeed = wheel.AngularVelocity * wheel.Radius; + float wheelSlip = wheelLinearSpeed - vehicleSpeed; + + if ( wheelSlip > 2.0f ) + { + TCSActive = true; + wheel.BrakeTorque = wheelSlip * 1000; + } + } + } +} diff --git a/Code/Car/VeloXCar.cs b/Code/Car/VeloXCar.cs index db9c367..a6842b8 100644 --- a/Code/Car/VeloXCar.cs +++ b/Code/Car/VeloXCar.cs @@ -15,6 +15,7 @@ public partial class VeloXCar : VeloXBase return; UpdateABS(); UpdateESC(); + UpdateTCS(); var dt = Time.Delta; //EngineThink( dt ); SimulateAerodinamics( dt ); @@ -26,7 +27,7 @@ public partial class VeloXCar : VeloXBase private void UpdateUnflip( float dt ) { - if ( Math.Abs( inputSteer ) < 0.1f ) + if ( Math.Abs( SteeringAngle ) < 0.1f ) return; if ( IsOnGround || Math.Abs( WorldRotation.Roll() ) < 60 ) @@ -42,7 +43,7 @@ public partial class VeloXCar : VeloXBase if ( velocityFactor <= 0.01f ) return; - var force = inputSteer * velocityFactor * 150; + var force = SteeringAngle * velocityFactor * 150; Body.AngularVelocity -= Body.WorldRotation.Forward * force * dt; } diff --git a/Code/Input/InputResolver.cs b/Code/Input/InputResolver.cs index 3daada3..f6a960b 100644 --- a/Code/Input/InputResolver.cs +++ b/Code/Input/InputResolver.cs @@ -4,13 +4,10 @@ namespace VeloX; public class InputResolver { - public Connection Driver { get; internal set; } - private bool IsDriverActive => Driver is not null; - - public Vector2 MouseDelta => IsDriverActive ? Input.MouseDelta : default; - public Vector2 MouseWheel => IsDriverActive ? Input.MouseWheel : default; - public Angles AnalogLook => IsDriverActive ? Input.AnalogLook : default; + public Vector2 MouseDelta => Input.MouseDelta; + public Vector2 MouseWheel => Input.MouseWheel; + public Angles AnalogLook => Input.AnalogLook; public Vector3 AnalogMove { get @@ -22,22 +19,19 @@ public class InputResolver input.y = -Input.GetAnalog( InputAnalog.LeftStickX ); return input; } - return IsDriverActive ? Input.AnalogMove : default; + return Input.AnalogMove; } } public bool Down( string action ) { - return IsDriverActive && Input.Down( action ); + return Input.Down( action ); } public float Brake { get { - if ( !IsDriverActive ) - return 0; - if ( Input.UsingController ) return Input.GetAnalog( InputAnalog.LeftTrigger ); @@ -48,9 +42,6 @@ public class InputResolver { get { - if ( !IsDriverActive ) - return 0; - if ( Input.UsingController ) return Input.GetAnalog( InputAnalog.RightTrigger ); @@ -60,37 +51,30 @@ public class InputResolver public bool Pressed( string action ) { - return IsDriverActive && Input.Pressed( action ); + return Input.Pressed( action ); } public bool Released( string action ) { - return IsDriverActive && Input.Released( action ); + return Input.Released( action ); } public float GetAnalog( InputAnalog analog ) { - return IsDriverActive ? Input.GetAnalog( analog ) : 0f; + return Input.GetAnalog( analog ); } public void TriggerHaptics( float leftMotor, float rightMotor, float leftTrigger = 0f, float rightTrigger = 0f, int duration = 500 ) { - if ( IsDriverActive ) - { - Input.TriggerHaptics( leftMotor, rightMotor, leftTrigger, rightTrigger, duration ); - } + Input.TriggerHaptics( leftMotor, rightMotor, leftTrigger, rightTrigger, duration ); } public void TriggerHaptics( HapticEffect effect, float lengthScale = 1, float frequencyScale = 1, float amplitudeScale = 1 ) { - if ( IsDriverActive ) - { - Input.TriggerHaptics( effect, lengthScale, frequencyScale, amplitudeScale ); - } + Input.TriggerHaptics( effect, lengthScale, frequencyScale, amplitudeScale ); } public void StopAllHaptics() { - if ( IsDriverActive ) - Input.StopAllHaptics(); + Input.StopAllHaptics(); } }