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();
}
}