velox/Code/Base/Wheel/VeloXWheel.Smoke.cs
2025-11-06 12:13:30 +07:00

110 lines
2.9 KiB
C#

using Sandbox;
using System;
using System.Collections.Generic;
using System.Threading;
namespace VeloX;
public partial class VeloXWheel
{
private static readonly GameObject SmokePrefab = GameObject.GetPrefab( "prefabs/particles/tire_smoke.prefab" );
private GameObject SmokeObject { get; set; }
public const float MIN_DRIFT_ANGLE = 10f;
public const float MIN_DRIFT_SPEED = 30f;
public const float MAX_DRIFT_ANGLE = 110f;
private float smokeMul;
private float timeMul;
protected override void OnStart()
{
base.OnStart();
if ( IsProxy )
return;
if ( !SmokeObject.IsValid() )
SmokeObject = GameObject.GetPrefab( "prefabs/particles/tire_smoke.prefab" ).Clone( new CloneConfig() { Parent = GameObject, StartEnabled = true } );
}
public float GetSlip()
{
if ( !IsOnGround )
return 0;
var val = Math.Abs( LateralSlip ) + Math.Abs( LongitudinalSlip );
timeMul = timeMul.LerpTo( val, 0.1f );
if ( timeMul > 2 )
return val;
return 0;
}
protected override void OnUpdate()
{
base.OnUpdate();
if ( IsProxy )
return;
UpdateSkid();
SmokeObject.WorldPosition = ContactPosition + Vehicle.WorldRotation.Down * Radius.MeterToInch();
smokeMul = Math.Max( 0, GetSlip() - 3 );
bool density = false;
if ( smokeMul > 0 )
density = true;
var emitter = SmokeObject.Components.Get<ParticleSphereEmitter>( FindMode.EverythingInSelfAndDescendants );
emitter.Enabled = density;
emitter.Radius = 0f;
emitter.Velocity = 0;
emitter.Duration = 5;
emitter.Burst = 5;
float sizeMul = 0.7f + smokeMul * 0.3f;
emitter.Rate = smokeMul * 100f;
emitter.RateOverDistance = smokeMul * 10f;
var effect = SmokeObject.Components.Get<ParticleEffect>( FindMode.EverythingInSelfAndDescendants );
effect.MaxParticles = 500;
effect.Damping = 0.9f;
effect.ApplyRotation = true;
effect.ApplyShape = true;
effect.Roll = new()
{
Type = ParticleFloat.ValueType.Range,
Evaluation = ParticleFloat.EvaluationType.Seed,
ConstantA = 0,
ConstantB = 360,
};
effect.Scale = new()
{
Type = ParticleFloat.ValueType.Curve,
Evaluation = ParticleFloat.EvaluationType.Life,
CurveA = new( new List<Curve.Frame>() { new( 0, 10f ), new( 0.8f, 50f ), new( 1f, 160f * sizeMul ) } ),
};
effect.StartDelay = 0.025f + (1 - smokeMul) * 0.03f;
effect.ApplyColor = true;
effect.Gradient = new()
{
Type = ParticleGradient.ValueType.Range,
Evaluation = ParticleGradient.EvaluationType.Particle,
ConstantA = Color.White,
ConstantB = Color.Transparent,
};
effect.StartVelocity = new()
{
Type = ParticleFloat.ValueType.Range,
Evaluation = ParticleFloat.EvaluationType.Seed,
ConstantA = 10,
ConstantB = 70,
};
effect.Force = true;
effect.InitialVelocity = hitForwardDirection * LongitudinalSlip * 10f;
effect.ForceDirection = 0;
effect.SheetSequence = true;
effect.SequenceSpeed = 0.5f;
effect.SequenceTime = 1f;
}
}