@name Realistic Engine [Rework] Audi TT @inputs [Axles]:array [Throttle Clutch GearUp GearDown]:number [FLW FRW RLW RRW]:entity @outputs [IdleRPM MaxRPM RPM FinalDrive EngineTorque MaxTorque LoadTorque MasterThrottle]:number @outputs [ClutchRPM ClutchSlip ClutchStiffness ClutchCapacity ClutchMaxTorque ClutchDamping ClutchTorque LastClutchTorque]:number @outputs [Gear GearRatio GearboxRPM GearboxTorque]:number @persist [AxlesPowerMap TorqueMap]:array [MasterThrottle FlywheelMass FlywheelRadius FlywheelInertia StartFriction FrictionCoeff LimiterDuration LimiterTime LoadTorque]:number @persist [ClutchRPM ClutchSlip ClutchStiffness ClutchCapacity ClutchMaxTorque ClutchDamping ClutchTorque LastClutchTorque]:number @persist [GearRatios]:array [Gear GearRatio]:number @persist M:number @inputs [B]:entity @outputs [LWCorrectingTorque RWCorrectingTorque] @outputs [AverageRPM] @persist [LWTq RWTq] [LWAV RWAV] @persist [LWDampingTq RWDampingTq] @persist [LWPowerCoeff RWPowerCoeff] @persist [LWCorrectedTorque RWCorrectedTorque] @persist UsedCoeff @persist [Power Coast Preload] LimitTorque UsePowerBias @persist ViscousCoeff TickInterval @model models/engines/inline4s.mdl @trigger none #include "libs/math" if (duped()|dupefinished()) { reset() } if (first()) { M = 1 # --- ENGINE IdleRPM = 900 MaxRPM = 7000 FlywheelMass = 4.9 FlywheelRadius = 0.378 StartFriction = -50 FrictionCoeff = 0.02 LimiterDuration = 0.05 TorqueMap = array( 240.29618749947, 251.33093929699, 262.3656910945, 273.40044289202, 284.43519468953, 295.46994648705, 306.50469828456, 317.53945008208, 328.57420187959, 339.60895367711, 350.64370547463, 361.67845727214, 372.71320906966, 383.74796086717, 394.78271266469, 405.8174644622, 416.85221625972, 427.88696805724, 438.92171985475, 449.95647165227, 449.9557104607, 449.95494926913, 449.95418807757, 449.953426886, 449.95266569443, 449.95190450287, 449.9511433113, 449.95038211973, 449.94962092816, 449.9488597366, 449.94809854503, 449.94733735346, 449.9465761619, 449.94581497033, 449.94505377876, 449.9442925872, 449.94353139563, 449.94277020406, 449.94200901249, 449.94124782093, 449.94048662936, 449.93972543779, 449.93896424623, 449.93820305466, 449.93744186309, 449.93668067153, 449.93591947996, 449.93515828839, 449.93439709682, 449.93363590526, 449.93287471369, 449.93211352212, 449.93135233056, 449.93059113899, 449.92982994742, 449.92906875586, 449.92830756429, 449.92754637272, 449.92678518115, 449.92602398959, 449.92526279802, 449.92450160645, 449.92374041489, 449.92297922332, 449.92221803175, 449.92145684019, 449.92069564862, 449.91993445705, 449.91917326548, 449.91841207392, 449.91765088235, 449.91688969078, 449.91612849922, 446.34504740794, 442.77396631665, 439.20288522537, 435.63180413409, 432.06072304281, 428.48964195153, 424.91856086025, 421.34747976897, 417.77639867769, 414.2053175864, 410.63423649512, 407.06315540384, 403.49207431256, 399.92099322128, 396.34991213, 392.77883103872, 389.20774994744, 385.63666885615, 382.06558776487, 378.49450667359, 374.92342558231, 371.35234449103, 367.78126339975, 364.21018230847, 360.63910121719, 357.0680201259, 353.49693903462, 349.92585794334 ) # --- CLUTCH ClutchStiffness = 22 ClutchCapacity = 1.3 ClutchDamping = 0.5 GearRatios = array(-14.41, 0, 13.45, 8.12, 5.51, 4.16, 3.36, 2.83) FinalDrive = 1 # --- Differential Power = 0.1 Coast = 0.05 Preload = 10 UsePowerBias = 10 ViscousCoeff = 0.96 # --- function void shiftGear(Direction:number) { local PrevGear = Gear Gear = clamp(Gear + Direction, -1, GearRatios:count() - 2) GearRatio = GearRatios[Gear + 2, number] } function number remap(Value:number, A1:number, A2:number, B1:number, B2:number) { return B1 + (B2 - B1) * (Value - A1) / (A2 - A1) } function number processAxle(Torque:number, LW:entity, RW:entity) { local Axle = vec(0,1,0) # Basic velocity calculations local LWAV = toRad(LW:angVelVector():y()) local RWAV = toRad(RW:angVelVector():y()) * -1 # RAV = relative angular velocity local LWRAV = RWAV - LWAV local RWRAV = LWAV - RWAV local LWTq = LWRAV * LW:inertia():y() local RWTq = RWRAV * RW:inertia():y() # Calculating damping torque local LWDampingTq = ViscousCoeff * LWTq local RWDampingTq = ViscousCoeff * RWTq # Whether use diff power or diff coast local UsePower = abs(Torque) > UsePowerBias local UsedCoeff = UsePower ? Power : Coast local LWPowerCoeff = 0 local RWPowerCoeff = 0 if (LWTq - RWTq > Preload) { LWPowerCoeff = UsedCoeff RWPowerCoeff = 1 + (1 - UsedCoeff) } elseif (RWTq - LWTq > Preload) { RWPowerCoeff = UsedCoeff LWPowerCoeff = 1 + (1 - UsedCoeff) } else { LWPowerCoeff = 1 RWPowerCoeff = 1 } LWCorrectingTorque = clamp(LWDampingTq * LWPowerCoeff, -LimitTorque, LimitTorque) RWCorrectingTorque = clamp(RWDampingTq * RWPowerCoeff, -LimitTorque, LimitTorque) # Calculating final applied torque here LWCorrectedTorque = LWCorrectingTorque + Torque / 2 RWCorrectedTorque = RWCorrectingTorque + Torque / 2 LW:applyTorque(LWCorrectedTorque * Axle * 52.49) RW:applyTorque(RWCorrectedTorque * Axle * -1 * 52.49) return (LW:angVelVector():y() + RW:angVelVector():y() * -1) / 2 / 6 } MaxTorque = TorqueMap:max() * M ClutchMaxTorque = 900 GearRatio = GearRatios[Gear + 2, number] FlywheelInertia = FlywheelMass * FlywheelRadius ^ 2 / 2 EngineAngVel = IdleRPM / 9.5493 LimitTorque = ClutchMaxTorque RPM = IdleRPM LimiterTime = 0 runOnTick(1) } if ((changed(GearUp) && GearUp) || changed(GearDown) && GearDown) { shiftGear(GearUp - GearDown) } if (tickClk()) { GearboxTorque = ClutchTorque * GearRatio * FinalDrive local AxelsRPM = max(processAxle(GearboxTorque / 2, FLW, FRW), processAxle(GearboxTorque / 2, RLW, RRW)) GearboxRPM = AxelsRPM * FinalDrive * GearRatio ClutchSlip = ((RPM * 0.10472) - (GearboxRPM * 0.10472)) * (GearRatio != 0) / 2 local A = clamp(ClutchSlip * ClutchStiffness * (1 - Clutch), -ClutchMaxTorque, ClutchMaxTorque) ClutchTorque = interpolate(ClutchTorque, A, ClutchDamping) local LoadTorque = ClutchTorque local RPMFraction = clamp((RPM - IdleRPM) / (MaxRPM - IdleRPM), 0, 1) local Friction = StartFriction - RPM * FrictionCoeff local MaxInitialTorque = TorqueMap[clamp(floor(RPMFraction * 100), 0, 100) + 1, number] * M - Friction local IdleFade = clamp(remap(RPM, IdleRPM, IdleRPM + 600, 1, 0), 0, 1)#clamp(0 + (RPM - (IdleRPM + 500)) * (1 - 0) / (IdleRPM - (IdleRPM + 500)), 0, 1) local IdleFade2 = clamp(remap(RPM, IdleRPM - 300, IdleRPM, 1, 0), 0, 1) local AdditionalEngineSupply = (IdleFade) * (-Friction / MaxInitialTorque) + IdleFade2 if (RPM >= MaxRPM) { Throttle = 0 LimiterTime = systime() } else { Throttle *= systime() >= LimiterTime + LimiterDuration } MasterThrottle = clamp(AdditionalEngineSupply + Throttle, 0, 1) local RealInitialTorque = MaxInitialTorque * MasterThrottle EngineTorque = RealInitialTorque + Friction RPM += (EngineTorque - LoadTorque) / FlywheelInertia * 9.5493 * tickInterval() RPM = max(RPM, 0) B:applyTorque(vec(0, -GearboxTorque * 20, 0)) }