--[[ | This file was obtained through the combined efforts | of Madbluntz & Plymouth Antiquarian Society. | | Credits: lifestorm, Gregory Wayne Rossel JR., | Maloy, DrPepper10 @ RIP, Atle! | | Visit for more: https://plymouth.thetwilightzone.ru/ --]] function ENT:WheelOnGround() self.FrontWheelPowered = self:GetPowerDistribution() ~= 1 self.RearWheelPowered = self:GetPowerDistribution() ~= -1 for i = 1, table.Count( self.Wheels ) do local Wheel = self.Wheels[i] if not IsValid( Wheel ) then continue end local dmgMul = Wheel:GetDamaged() and 0.5 or 1 local surfacemul = simfphys.TractionData[Wheel:GetSurfaceMaterial():lower()] self.VehicleData[ "SurfaceMul_" .. i ] = (surfacemul and math.max(surfacemul,0.001) or 1) * dmgMul local WheelPos = self:LogicWheelPos( i ) local WheelRadius = WheelPos.IsFrontWheel and self.FrontWheelRadius or self.RearWheelRadius local startpos = Wheel:GetPos() local dir = -self.Up local len = WheelRadius + math.Clamp(-self.Vel.z / 50,2.5,6) local HullSize = Vector(WheelRadius,WheelRadius,0) local tr = util.TraceHull( { start = startpos, endpos = startpos + dir * len, maxs = HullSize, mins = -HullSize, filter = self.VehicleData["filter"] } ) if tr.Hit then self.VehicleData[ "onGround_" .. i ] = 1 Wheel:SetSpeed( Wheel.FX ) Wheel:SetSkidSound( Wheel.skid ) Wheel:SetSurfaceMaterial( util.GetSurfacePropName( tr.SurfaceProps ) ) Wheel:SetOnGround(1) else self.VehicleData[ "onGround_" .. i ] = 0 Wheel:SetOnGround(0) end end local FrontOnGround = math.max(self.VehicleData[ "onGround_1" ],self.VehicleData[ "onGround_2" ]) local RearOnGround = math.max(self.VehicleData[ "onGround_3" ],self.VehicleData[ "onGround_4" ],self.VehicleData[ "onGround_5" ],self.VehicleData[ "onGround_6" ]) self.DriveWheelsOnGround = math.max(self.FrontWheelPowered and FrontOnGround or 0,self.RearWheelPowered and RearOnGround or 0) end function ENT:SimulateAirControls(tilt_forward,tilt_back,tilt_left,tilt_right) if self:IsDriveWheelsOnGround() then return end if hook.Run( "simfphysAirControl", self, tilt_forward, tilt_back, tilt_left, tilt_right) then return end local PObj = self:GetPhysicsObject() local TiltForce = ((self.Right * (tilt_right - tilt_left) * 1.8) + (self.Forward * (tilt_forward - tilt_back) * 6)) * math.acos( math.Clamp( self.Up:Dot(Vector(0,0,1)) ,-1,1) ) * (180 / math.pi) * self.Mass PObj:ApplyForceOffset( TiltForce, PObj:GetMassCenter() + self.Up ) PObj:ApplyForceOffset( -TiltForce, PObj:GetMassCenter() - self.Up ) end function ENT:SimulateEngine(IdleRPM,LimitRPM,Powerbandstart,Powerbandend,c_time) local PObj = self:GetPhysicsObject() local IsRunning = self:EngineActive() local Throttle = self:GetThrottle() if not self:IsDriveWheelsOnGround() then self.Clutch = 1 end if self.Gears[self.CurrentGear] == 0 then self.GearRatio = 1 self.Clutch = 1 self.HandBrake = self.HandBrake + (self.HandBrakePower - self.HandBrake) * 0.2 else self.GearRatio = self.Gears[self.CurrentGear] * self:GetDiffGear() end self:SetClutch( self.Clutch ) local InvClutch = 1 - self.Clutch local GearedRPM = self.WheelRPM / math.abs(self.GearRatio) local MaxTorque = self:GetMaxTorque() local DesRPM = Lerp(InvClutch, math.max(IdleRPM + (LimitRPM - IdleRPM) * Throttle,0), GearedRPM ) local Drag = (MaxTorque * (math.max( self.EngineRPM - IdleRPM, 0) / Powerbandend) * ( 1 - Throttle) / 0.15) * InvClutch local TurboCharged = self:GetTurboCharged() local SuperCharged = self:GetSuperCharged() local boost = (TurboCharged and self:SimulateTurbo(Powerbandend) or 0) * 0.3 + (SuperCharged and self:SimulateBlower(Powerbandend) or 0) if self:GetCurHealth() <= self:GetMaxHealth() * 0.3 then MaxTorque = MaxTorque * (self:GetCurHealth() / (self:GetMaxHealth() * 0.3)) end self.EngineRPM = math.Clamp(self.EngineRPM + math.Clamp(DesRPM - self.EngineRPM,-math.max(self.EngineRPM / 15, 1 ),math.max(-self.RpmDiff / 1.5 * InvClutch + (self.Torque * 5) / 0.15 * self.Clutch, 1)) + self.RPM_DIFFERENCE * Throttle,0,LimitRPM) * self.EngineIsOn self.Torque = (Throttle + boost) * math.max(MaxTorque * math.min(self.EngineRPM / Powerbandstart, (LimitRPM - self.EngineRPM) / (LimitRPM - Powerbandend),1), 0) self:SetFlyWheelRPM( math.min(self.EngineRPM + self.exprpmdiff * 2 * InvClutch,LimitRPM) ) self.RpmDiff = self.EngineRPM - GearedRPM local signGearRatio = ((self.GearRatio > 0) and 1 or 0) + ((self.GearRatio < 0) and -1 or 0) local signThrottle = (Throttle > 0) and 1 or 0 local signSpeed = ((self.ForwardSpeed > 0) and 1 or 0) + ((self.ForwardSpeed < 0) and -1 or 0) local TorqueDiff = (self.RpmDiff / LimitRPM) * 0.15 * self.Torque local EngineBrake = (signThrottle == 0) and math.min( self.EngineRPM * (self.EngineRPM / LimitRPM) ^ 2 / 60 * signSpeed, 100 ) or 0 local GearedPower = ((self.ThrottleDelay <= c_time and (self.Torque + TorqueDiff) * signThrottle * signGearRatio or 0) - EngineBrake) / math.abs(self.GearRatio) / 50 self.EngineTorque = IsRunning and GearedPower * InvClutch or 0 if not self:GetDoNotStall() then if IsRunning then if self.EngineRPM <= IdleRPM * 0.2 then self.CurrentGear = 2 self:StallAndRestart() end end end if simfphys.Fuel then local FuelUse = (Throttle * 0.3 + 0.7) * ((self.EngineRPM / LimitRPM) * MaxTorque + self.Torque) / 1500000 local Fuel = self:GetFuel() self:SetFuel( Fuel - FuelUse * (1 / simfphys.FuelMul) ) self.UsedFuel = self.UsedFuel and (self.UsedFuel + FuelUse) or 0 self.CheckUse = self.CheckUse or 0 if self.CheckUse < CurTime() then self.CheckUse = CurTime() + 1 self:SetFuelUse( self.UsedFuel * 60 ) self.UsedFuel = 0 end if Fuel <= 0 and IsRunning then self:StopEngine() end else self:SetFuelUse( -1 ) end local ReactionForce = (self.EngineTorque * 2 - math.Clamp(self.ForwardSpeed,-self.Brake,self.Brake)) * self.DriveWheelsOnGround local BaseMassCenter = PObj:GetMassCenter() local dt_mul = math.max( math.min(self:GetPowerDistribution() + 0.5,1),0) PObj:ApplyForceOffset( -self.Forward * self.Mass * ReactionForce, BaseMassCenter + self.Up * dt_mul ) PObj:ApplyForceOffset( self.Forward * self.Mass * ReactionForce, BaseMassCenter - self.Up * dt_mul ) end function ENT:SimulateTransmission(k_throttle,k_brake,k_fullthrottle,k_clutch,k_handbrake,k_gearup,k_geardown,isauto,IdleRPM,Powerbandstart,Powerbandend,shiftmode,cruisecontrol,curtime) local GearsCount = table.Count( self.Gears ) local cruiseThrottle = math.min( math.max(self.cc_speed - math.abs(self.ForwardSpeed),0) / 10 ^ 2, 1) if isnumber(self.ForceTransmission) then isauto = self.ForceTransmission <= 1 end if not isauto then self.Brake = self:GetBrakePower() * math.max( k_brake, self.PressedKeys["joystick_brake"] ) self.HandBrake = self.HandBrakePower * k_handbrake self.Clutch = math.max( k_clutch, k_handbrake, self.PressedKeys["joystick_clutch"] ) local AutoThrottle = self:EngineActive() and ((self.EngineRPM < IdleRPM) and (IdleRPM - self.EngineRPM) / IdleRPM or 0) or 0 local Throttle = cruisecontrol and cruiseThrottle or ( math.max( (0.5 + 0.5 * k_fullthrottle) * k_throttle, self.PressedKeys["joystick_throttle"] ) + AutoThrottle) self:SetThrottle( Throttle ) if k_gearup ~= self.GearUpPressed then self.GearUpPressed = k_gearup if k_gearup == 1 then if self.CurrentGear ~= GearsCount then self.ThrottleDelay = curtime + 0.4 - 0.4 * k_clutch end self.CurrentGear = math.Clamp(self.CurrentGear + 1,1,GearsCount) end end if k_geardown ~= self.GearDownPressed then self.GearDownPressed = k_geardown if k_geardown == 1 then self.CurrentGear = math.Clamp(self.CurrentGear - 1,1,GearsCount) if self.CurrentGear == 1 then self.ThrottleDelay = curtime + 0.25 end end end else local throttleMod = 0.5 + 0.5 * k_fullthrottle local throttleForward = math.max( k_throttle * throttleMod, self.PressedKeys["joystick_throttle"] ) local throttleReverse = math.max( k_brake * throttleMod, self.PressedKeys["joystick_brake"] ) local throttleStanding = math.max( k_throttle * throttleMod, k_brake * throttleMod, self.PressedKeys["joystick_brake"], self.PressedKeys["joystick_throttle"] ) local inputThrottle = self.ForwardSpeed >= 50 and throttleForward or ((self.ForwardSpeed < 50 and self.ForwardSpeed > -350) and throttleStanding or throttleReverse) local Throttle = cruisecontrol and cruiseThrottle or inputThrottle local CalcRPM = self.EngineRPM - self.RPM_DIFFERENCE * Throttle self:SetThrottle( Throttle ) if self.CurrentGear <= 3 and Throttle > 0 and self.CurrentGear ~= 2 then if Throttle < 1 and not cruisecontrol then local autoclutch = math.Clamp((Powerbandstart / self.EngineRPM) - 0.5,0,1) self.sm_autoclutch = self.sm_autoclutch and (self.sm_autoclutch + math.Clamp(autoclutch - self.sm_autoclutch,-0.2,0.1) ) or 0 else self.sm_autoclutch = (self.EngineRPM < IdleRPM + (Powerbandstart - IdleRPM)) and 1 or 0 end else self.sm_autoclutch = 0 end self.Clutch = math.max(self.sm_autoclutch,k_handbrake) self.HandBrake = self.HandBrakePower * k_handbrake self.Brake = self:GetBrakePower() * (self.ForwardSpeed >= 0 and math.max(k_brake,self.PressedKeys["joystick_brake"]) or math.max(k_throttle,self.PressedKeys["joystick_throttle"])) if self:IsDriveWheelsOnGround() then if self.ForwardSpeed >= 50 then if self.Clutch == 0 then local NextGear = self.CurrentGear + 1 <= GearsCount and math.min(self.CurrentGear + 1,GearsCount) or self.CurrentGear local NextGearRatio = self.Gears[NextGear] * self:GetDiffGear() local NextGearRPM = self.WheelRPM / math.abs(NextGearRatio) local PrevGear = self.CurrentGear - 1 <= GearsCount and math.max(self.CurrentGear - 1,3) or self.CurrentGear local PrevGearRatio = self.Gears[PrevGear] * self:GetDiffGear() local PrevGearRPM = self.WheelRPM / math.abs(PrevGearRatio) local minThrottle = shiftmode == 1 and 1 or math.max(Throttle,0.5) local ShiftUpRPM = Powerbandstart + (Powerbandend - Powerbandstart) * minThrottle local ShiftDownRPM = IdleRPM + (Powerbandend - Powerbandstart) * minThrottle local CanShiftUp = NextGearRPM > math.max(Powerbandstart * minThrottle,Powerbandstart - IdleRPM) and CalcRPM >= ShiftUpRPM and self.CurrentGear < GearsCount local CanShiftDown = CalcRPM <= ShiftDownRPM and PrevGearRPM < ShiftDownRPM and self.CurrentGear > 3 if CanShiftUp and self.NextShift < curtime then self.CurrentGear = self.CurrentGear + 1 self.NextShift = curtime + 0.5 self.ThrottleDelay = curtime + 0.25 end if CanShiftDown and self.NextShift < curtime then self.CurrentGear = self.CurrentGear - 1 self.NextShift = curtime + 0.35 end self.CurrentGear = math.Clamp(self.CurrentGear,3,GearsCount) end elseif (self.ForwardSpeed < 50 and self.ForwardSpeed > -350) then self.CurrentGear = (k_throttle == 1 and 3 or k_brake == 1 and 1 or self.PressedKeys["joystick_throttle"] > 0 and 3 or self.PressedKeys["joystick_brake"] > 0 and 1) or 3 self.Brake = self:GetBrakePower() * math.max(k_throttle * k_brake,self.PressedKeys["joystick_throttle"] * self.PressedKeys["joystick_brake"]) elseif (self.ForwardSpeed >= -350) then if (Throttle > 0) then self.Brake = 0 end self.CurrentGear = 1 end if (Throttle == 0 and math.abs(self.ForwardSpeed) <= 80) then self.CurrentGear = 2 self.Brake = 0 end end end self:SetIsBraking( self.Brake > 0 ) self:SetGear( self.CurrentGear ) self:SetHandBrakeEnabled( self.HandBrake > 0 or self.CurrentGear == 2 ) if self.Clutch == 1 or self.CurrentGear == 2 then if math.abs(self.ForwardSpeed) <= 20 then local PObj = self:GetPhysicsObject() local TiltForce = self.Torque * (-1 + self:GetThrottle() * 2) PObj:ApplyForceOffset( self.Up * TiltForce, PObj:GetMassCenter() + self.Right * 1000 ) PObj:ApplyForceOffset( -self.Up * TiltForce, PObj:GetMassCenter() - self.Right * 1000) end end end function ENT:GetTransformedDirection() local SteerAngForward = self.Forward:Angle() local SteerAngRight = self.Right:Angle() local SteerAngForward2 = self.Forward:Angle() local SteerAngRight2 = self.Right:Angle() SteerAngForward:RotateAroundAxis(-self.Up, self.VehicleData[ "Steer" ]) SteerAngRight:RotateAroundAxis(-self.Up, self.VehicleData[ "Steer" ]) SteerAngForward2:RotateAroundAxis(-self.Up, -self.VehicleData[ "Steer" ]) SteerAngRight2:RotateAroundAxis(-self.Up, -self.VehicleData[ "Steer" ]) local SteerForward = SteerAngForward:Forward() local SteerRight = SteerAngRight:Forward() local SteerForward2 = SteerAngForward2:Forward() local SteerRight2 = SteerAngRight2:Forward() return {Forward = SteerForward,Right = SteerRight,Forward2 = SteerForward2, Right2 = SteerRight2} end function ENT:LogicWheelPos( index ) local IsFront = index == 1 or index == 2 local IsRight = index == 2 or index == 4 or index == 6 return {IsFrontWheel = IsFront, IsRightWheel = IsRight} end function ENT:SimulateWheels(k_clutch,LimitRPM) local Steer = self:GetTransformedDirection() local MaxGrip = self:GetMaxTraction() local Efficiency = self:GetEfficiency() local GripOffset = self:GetTractionBias() * MaxGrip local wVel = 0 for i = 1, table.Count( self.Wheels ) do local Wheel = self.Wheels[i] if IsValid( Wheel ) then local WheelPos = self:LogicWheelPos( i ) local WheelRadius = WheelPos.IsFrontWheel and self.FrontWheelRadius or self.RearWheelRadius local WheelDiameter = WheelRadius * 2 local SurfaceMultiplicator = self.VehicleData[ "SurfaceMul_" .. i ] local MaxTraction = (WheelPos.IsFrontWheel and (MaxGrip + GripOffset) or (MaxGrip - GripOffset)) * SurfaceMultiplicator local IsPoweredWheel = (WheelPos.IsFrontWheel and self.FrontWheelPowered or not WheelPos.IsFrontWheel and self.RearWheelPowered) and 1 or 0 local Velocity = Wheel:GetVelocity() local VelForward = Velocity:GetNormalized() local OnGround = self.VehicleData[ "onGround_" .. i ] local Forward = WheelPos.IsFrontWheel and Steer.Forward or self.Forward local Right = WheelPos.IsFrontWheel and Steer.Right or self.Right if self.CustomWheels then if WheelPos.IsFrontWheel then Forward = IsValid(self.SteerMaster) and Steer.Forward or self.Forward Right = IsValid(self.SteerMaster) and Steer.Right or self.Right else if IsValid( self.SteerMaster2 ) then Forward = Steer.Forward2 Right = Steer.Right2 end end end local Ax = math.deg( math.acos( math.Clamp( Forward:Dot(VelForward) ,-1,1) ) ) local Ay = math.deg( math.asin( math.Clamp( Right:Dot(VelForward) ,-1,1) ) ) local Fx = math.cos( math.rad( Ax ) ) * Velocity:Length() local Fy = math.sin( math.rad( Ay ) ) * Velocity:Length() local absFy = math.abs(Fy) local absFx = math.abs(Fx) local PowerBiasMul = WheelPos.IsFrontWheel and (1 - self:GetPowerDistribution()) * 0.5 or (1 + self:GetPowerDistribution()) * 0.5 local BrakeForce = math.Clamp(-Fx,-self.Brake,self.Brake) * SurfaceMultiplicator local TorqueConv = self.EngineTorque * PowerBiasMul * IsPoweredWheel local ForwardForce = TorqueConv + (not WheelPos.IsFrontWheel and math.Clamp(-Fx,-self.HandBrake,self.HandBrake) or 0) + BrakeForce * 0.5 local TractionCycle = Vector(math.min(absFy,MaxTraction),ForwardForce,0):Length() local GripLoss = math.max(TractionCycle - MaxTraction,0) local GripRemaining = math.max(MaxTraction - GripLoss,math.min(absFy / 25,MaxTraction)) --local GripRemaining = math.max(MaxTraction - GripLoss,math.min(absFy / 25,MaxTraction / 2)) local signForwardForce = ((ForwardForce > 0) and 1 or 0) + ((ForwardForce < 0) and -1 or 0) local signEngineTorque = ((self.EngineTorque > 0) and 1 or 0) + ((self.EngineTorque < 0) and -1 or 0) local Power = ForwardForce * Efficiency - GripLoss * signForwardForce + math.Clamp(BrakeForce * 0.5,-MaxTraction,MaxTraction) local Force = -Right * math.Clamp(Fy,-GripRemaining,GripRemaining) + Forward * Power local wRad = Wheel:GetDamaged() and Wheel.dRadius or WheelRadius local wFX = (Fx + GripLoss * 35 * signEngineTorque * IsPoweredWheel) local TurnWheel = (wFX / wRad * 1.85) + self.EngineRPM / 80 * (1 - OnGround) * IsPoweredWheel * (1 - k_clutch) Wheel.FX = Fx Wheel.skid = ((MaxTraction - (MaxTraction - Vector(absFy,math.abs(ForwardForce * 10),0):Length())) / MaxTraction) - 10 local RPM = Wheel:VelToRPM( absFx ) * OnGround local GripLossFaktor = math.Clamp(GripLoss,0,MaxTraction) / MaxTraction local abswFX = math.abs( wFX ) Wheel:SetRPM( Wheel:VelToRPM( wFX ) ) if IsPoweredWheel then if abswFX > wVel then wVel = abswFX end end self.VehicleData[ "WheelRPM_".. i ] = RPM self.VehicleData[ "GripLossFaktor_".. i ] = GripLossFaktor self.VehicleData[ "Exp_GLF_".. i ] = GripLossFaktor ^ 2 Wheel:SetGripLoss( GripLossFaktor ) local WheelOPow = math.abs( self.CurrentGear == 1 and math.min( TorqueConv, 0 ) or math.max( TorqueConv, 0 ) ) > 0 local FrontWheelCanTurn = (WheelOPow and 0 or self.Brake) < MaxTraction * 1.75 local RearWheelCanTurn = (self.HandBrake < MaxTraction) and (WheelOPow and 0 or self.Brake) < MaxTraction * 2 if WheelPos.IsFrontWheel then if FrontWheelCanTurn then self.VehicleData[ "spin_" .. i ] = self.VehicleData[ "spin_" .. i ] + TurnWheel end else if RearWheelCanTurn then self.VehicleData[ "spin_" .. i ] = self.VehicleData[ "spin_" .. i ] + TurnWheel end end if self.CustomWheels then local GhostEnt = self.GhostWheels[i] if IsValid( GhostEnt ) then local Angle = GhostEnt:GetAngles() local offsetang = WheelPos.IsFrontWheel and self.CustomWheelAngleOffset or (self.CustomWheelAngleOffset_R or self.CustomWheelAngleOffset) local Direction = GhostEnt:LocalToWorldAngles( offsetang ):Forward() local TFront = FrontWheelCanTurn and TurnWheel or 0 local TBack = RearWheelCanTurn and TurnWheel or 0 local AngleStep = WheelPos.IsFrontWheel and TFront or TBack Angle:RotateAroundAxis(Direction, WheelPos.IsRightWheel and AngleStep or -AngleStep) self.GhostWheels[i]:SetAngles( Angle ) end else self:SetPoseParameter(self.VehicleData[ "pp_spin_" .. i ],self.VehicleData[ "spin_" .. i ]) end if not self.PhysicsEnabled then Wheel:GetPhysicsObject():ApplyForceCenter( Force * 185 * OnGround ) end end end self:SetWheelVelocity( wVel ) local target_diff = math.max(LimitRPM * 0.95 - self.EngineRPM,0) if self.FrontWheelPowered and self.RearWheelPowered then self.WheelRPM = math.max(self.VehicleData[ "WheelRPM_1" ] or 0,self.VehicleData[ "WheelRPM_2" ] or 0,self.VehicleData[ "WheelRPM_3" ] or 0,self.VehicleData[ "WheelRPM_4" ] or 0) self.RPM_DIFFERENCE = target_diff * math.max(self.VehicleData[ "GripLossFaktor_1" ] or 0,self.VehicleData[ "GripLossFaktor_2" ] or 0,self.VehicleData[ "GripLossFaktor_3" ] or 0,self.VehicleData[ "GripLossFaktor_4" ] or 0) self.exprpmdiff = target_diff * math.max(self.VehicleData[ "Exp_GLF_1" ] or 0,self.VehicleData[ "Exp_GLF_2" ] or 0,self.VehicleData[ "Exp_GLF_3" ] or 0,self.VehicleData[ "Exp_GLF_4" ] or 0) elseif not self.FrontWheelPowered and self.RearWheelPowered then self.WheelRPM = math.max(self.VehicleData[ "WheelRPM_3" ] or 0,self.VehicleData[ "WheelRPM_4" ] or 0) self.RPM_DIFFERENCE = target_diff * math.max(self.VehicleData[ "GripLossFaktor_3" ] or 0,self.VehicleData[ "GripLossFaktor_4" ] or 0) self.exprpmdiff = target_diff * math.max(self.VehicleData[ "Exp_GLF_3" ] or 0,self.VehicleData[ "Exp_GLF_4" ] or 0) elseif self.FrontWheelPowered and not self.RearWheelPowered then self.WheelRPM = math.max(self.VehicleData[ "WheelRPM_1" ] or 0,self.VehicleData[ "WheelRPM_2" ] or 0) self.RPM_DIFFERENCE = target_diff * math.max(self.VehicleData[ "GripLossFaktor_1" ] or 0,self.VehicleData[ "GripLossFaktor_2" ] or 0) self.exprpmdiff = target_diff * math.max(self.VehicleData[ "Exp_GLF_1" ] or 0,self.VehicleData[ "Exp_GLF_2" ] or 0) else self.WheelRPM = 0 self.RPM_DIFFERENCE = 0 self.exprpmdiff = 0 end end function ENT:SimulateTurbo(LimitRPM) if not self.Turbo then return end local Throttle = self:GetThrottle() self.SmoothTurbo = self.SmoothTurbo + math.Clamp(math.min(self.EngineRPM / LimitRPM,1) * 600 * (0.75 + 0.25 * Throttle) - self.SmoothTurbo,-15,15) local Volume = math.Clamp( ((self.SmoothTurbo - 300) / 150) ,0, 1) * 0.5 local Pitch = math.Clamp( self.SmoothTurbo / 7 , 0 , 255) local boost = math.Clamp( -0.25 + (self.SmoothTurbo / 500) ^ 5,0,1) self.Turbo:ChangeVolume( Volume ) self.Turbo:ChangePitch( Pitch ) return boost end function ENT:SimulateBlower(LimitRPM) if not self.Blower or not self.BlowerWhine then return end local Throttle = self:GetThrottle() self.SmoothBlower = self.SmoothBlower + math.Clamp(math.min(self.EngineRPM / LimitRPM,1) * 500 - self.SmoothBlower,-20,20) local Volume1 = math.Clamp( self.SmoothBlower / 400 * (1 - 0.4 * Throttle) ,0, 1) local Volume2 = math.Clamp( self.SmoothBlower / 400 * (0.10 + 0.4 * Throttle) ,0, 1) local Pitch1 = 50 + math.Clamp( self.SmoothBlower / 4.5 , 0 , 205) local Pitch2 = Pitch1 * 1.2 local boost = math.Clamp( (self.SmoothBlower / 600) ^ 4 ,0,1) self.Blower:ChangeVolume( Volume1 ) self.Blower:ChangePitch( Pitch1 ) self.BlowerWhine:ChangeVolume( Volume2 ) self.BlowerWhine:ChangePitch( Pitch2 ) return boost end