diff --git a/koptilnya/engine/clutch.txt b/koptilnya/engine/clutch.txt index 5ff835b..4a1e2c1 100644 --- a/koptilnya/engine/clutch.txt +++ b/koptilnya/engine/clutch.txt @@ -1,14 +1,14 @@ -Clutch = class("Clutch") +Clutch = class('Clutch') function Clutch:initialize(options) options = options or {} - self.stiffness = options.Stiffness or 0 - self.capacity = options.Capacity or 0 - self.damping = options.Damping or 0 - self.maxTorque = options.MaxTorque or 0 + self.stiffness = options.Stiffness or 10 + self.capacity = options.Capacity or 2 + self.damping = options.Damping or 0.3 + self.maxTorque = options.MaxTorque or 150 - self.press = 1 + self.press = 0 self.slip = 0 self.targetTorque = 0 self.torque = 0 @@ -25,9 +25,10 @@ function Clutch:update() local gboxRatio = self._gearbox and self._gearbox.ratio or 0 local gboxRatioNotZero = gboxRatio ~= 0 and 1 or 0 - self.slip = (engRPM * someConversionCoeff - gboxRPM * someConversionCoeff) * gboxRatioNotZero / 2 + self.slip = ((engRPM - gboxRPM) * someConversionCoeff) * gboxRatioNotZero / 2 self.targetTorque = math.clamp(self.slip * self.stiffness * (1 - self.press), -self.maxTorque, self.maxTorque) - self.torque = math.lerp(self.torque, self.targetTorque, self.damping) + + self.torque = math.lerp(self.damping, self.torque, self.targetTorque) end function Clutch:linkEngine(engine) @@ -37,3 +38,7 @@ end function Clutch:linkGearbox(gbox) self._gearbox = gbox end + +function Clutch:setPress(val) + self.press = math.clamp(val, 0, 1) +end diff --git a/koptilnya/engine/configs/audi_tt.txt b/koptilnya/engine/configs/audi_tt.txt index 229a768..c30793e 100644 --- a/koptilnya/engine/configs/audi_tt.txt +++ b/koptilnya/engine/configs/audi_tt.txt @@ -31,25 +31,30 @@ config = { Clutch = { Stiffness = 22, Capacity = 1.3, - Damping = 0.5 + Damping = 0.8, + MaxTorque = 600 }, Gearbox = { - Ratios = {2.93, 1.96, 1.38, 1.03, 1.06, 0.87}, - Reverse = 3.26, - FinalDrive = 4.77 + Ratios = {13.45, 8.12, 5.51, 4.16, 3.36, 2.83}, + Reverse = 14.41, + FinalDrive = 1 }, FrontDiff = { - Power = 0.25, - Coast = 0.15, + Power = 1, + Coast = 1, Preload = 10, UsePowerBias = 10, - ViscousCoeff = 0.96 + ViscousCoeff = 0.96, + Axle = Vector(1, 0, 0), + DistributionCoeff = 0.4 }, RearDiff = { - Power = 0.25, - Coast = 0.15, + Power = 1, + Coast = 1, Preload = 10, UsePowerBias = 10, - ViscousCoeff = 0.96 + ViscousCoeff = 0.96, + Axle = Vector(1, 0, 0), + DistributionCoeff = 0.6 } } diff --git a/koptilnya/engine/differential.txt b/koptilnya/engine/differential.txt index 4f7e679..908c284 100644 --- a/koptilnya/engine/differential.txt +++ b/koptilnya/engine/differential.txt @@ -1,18 +1,104 @@ -Differential = class("Differential") +-- @include ../libs/constants.txt +-- @include ../libs/table.txt +require('../libs/constants.txt') +require('../libs/table.txt') + +Differential = class('Differential') function Differential:initialize(options) - options = options or {} + options = options or {} - self.power = options.Power or 1 - self.coast = options.Coast or 1 - self.preload = options.Preload or 10 - self.viscousCoeff = options.ViscousCoeff or 0.9 + self.power = options.Power or 1 + self.coast = options.Coast or 1 + self.preload = options.Preload or 10 + self.viscousCoeff = options.ViscousCoeff or 0.9 + self.usePowerBias = options.UsePowerBias or 10 + self.axle = options.Axle or Vector(1, 0, 0) + self.distributionCoeff = options.DistributionCoeff or 1 - self._gearbox = options.Gearbox - self._leftWheel = options.LeftWheel - self._rightWheel = options.RightWheel + self.avgRPM = 0 - if self._gearbox then - self._gearbox:linkDiff(self) - end -end \ No newline at end of file + self._leftWheel = nil + self._rightWheel = nil + + self.lwInertia = Vector(0) + self.rwInertia = Vector(0) + + self.lwav = 0 + self.rwav = 0 + + self.lwtq = 0 + self.rwtq = 0 + + self.limitTorque = 250 +end + +function Differential:update() + if isValid(self._leftWheel) and isValid(self._rightWheel) then + self.lwav = math.rad(self._leftWheel:getAngleVelocity()[2]) + self.rwav = math.rad(self._rightWheel:getAngleVelocity()[2]) * -1 + + self.avgRPM = (self.lwav + self.rwav) / 2 * RAD_TO_RPM + + -- RAV = relative anglar velocity + local lwrav = self.rwav - self.lwav + local rwrav = self.lwav - self.rwav + + local lwtq = lwrav * self.lwInertia + local rwtq = rwrav * self.rwInertia + + -- Calculating damping torque here + local lwDampingTorque = self.viscousCoeff * lwtq + local rwDampingTorque = self.viscousCoeff * rwtq + + -- Whether use diff power or diff coast + local usePower = self._gearbox and self._gearbox.torque > self.usePowerBias or false + local usedCoeff = usePower and self.power or self.coast + + local lwPowerCoeff = usedCoeff + local rwPowerCoeff = usedCoeff + + -- this could probably be shortened? + -- if lwtq - rwtq > self.preload then + -- lwPowerCoeff = usedCoeff + -- rwPowerCoeff = usedCoeff + -- end + + -- if rwtq - lwtq > self.preload then + -- lwPowerCoeff = usedCoeff + -- rwPowerCoeff = usedCoeff + -- end + + local lwCorrectingTorque = math.clamp(lwDampingTorque * lwPowerCoeff, -self.limitTorque, self.limitTorque) + local rwCorrectingTorque = math.clamp(rwDampingTorque * rwPowerCoeff, -self.limitTorque, self.limitTorque) + + local gboxTorque = self._gearbox and self._gearbox.torque or 0 -- 6289.245 + + local lwCorrectedTorque = lwCorrectingTorque * 600 + gboxTorque * self.distributionCoeff * 52.49 + local rwCorrectedTorque = rwCorrectingTorque * 600 + gboxTorque * self.distributionCoeff * 52.49 + + self.lwtq = lwCorrectingTorque + self.rwtq = rwCorrectingTorque + + self._leftWheel:applyTorque(lwCorrectedTorque * -self._leftWheel:getRight() * TICK_INTERVAL) + self._rightWheel:applyTorque(rwCorrectedTorque * self._rightWheel:getRight() * TICK_INTERVAL) + end +end + +function Differential:linkWheels(left, right) + if isValid(left) and isValid(right) then + self._leftWheel = left + self._rightWheel = right + + self.lwInertia = left:getInertia():getLength() + self.rwInertia = right:getInertia():getLength() + end +end + +function Differential:linkGearbox(gbox) + if gbox ~= nil then + self._gearbox = gbox + + gbox:linkDiff(self) + end +end diff --git a/koptilnya/engine/eng_ref.lua b/koptilnya/engine/eng_ref.lua new file mode 100644 index 0000000..a5237df --- /dev/null +++ b/koptilnya/engine/eng_ref.lua @@ -0,0 +1,283 @@ +@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)) +} diff --git a/koptilnya/engine/engine.txt b/koptilnya/engine/engine.txt index 0f3caa2..b806718 100644 --- a/koptilnya/engine/engine.txt +++ b/koptilnya/engine/engine.txt @@ -1,7 +1,7 @@ -- @include ../libs/constants.txt -require("../libs/constants.txt") +require('../libs/constants.txt') -Engine = class("Engine") +Engine = class('Engine') function Engine:initialize(options) options = options or {} @@ -55,9 +55,9 @@ function Engine:update() if self.rpm > self.maxRPM then self.throttle = 0 - self._limiterTime = timer.realtime() + self._limiterTime = timer.systime() else - self.throttle = timer.realtime() >= self._limiterTime + self.limiterDuration and self.throttle or 0 + self.throttle = timer.systime() >= self._limiterTime + self.limiterDuration and self.throttle or 0 end local masterThrottle = math.clamp(additionalEnergySupply + self.throttle, 0, 1) diff --git a/koptilnya/engine/gearboxes/auto.txt b/koptilnya/engine/gearboxes/auto.txt index 56610c1..2ae1d3a 100644 --- a/koptilnya/engine/gearboxes/auto.txt +++ b/koptilnya/engine/gearboxes/auto.txt @@ -1,4 +1,4 @@ -- @include ./base.txt -require("./base.txt") +require('./base.txt') -AutomaticGearbox = class("AutomaticGearbox") \ No newline at end of file +AutomaticGearbox = class('AutomaticGearbox') \ No newline at end of file diff --git a/koptilnya/engine/gearboxes/base.txt b/koptilnya/engine/gearboxes/base.txt index d517f85..485cc81 100644 --- a/koptilnya/engine/gearboxes/base.txt +++ b/koptilnya/engine/gearboxes/base.txt @@ -1,4 +1,7 @@ -Gearbox = class("Gearbox") +-- @include ../../libs/table.txt +require('../../libs/table.txt') + +Gearbox = class('Gearbox') function Gearbox:initialize(options) options = options or {} @@ -7,8 +10,13 @@ function Gearbox:initialize(options) self.finalDrive = options.FinalDrive self.reverse = options.Reverse + self.rpm = 0 self.gear = 0 + self:recalcRatio() + + self.torque = 0 + self._linkedDiffs = {} self._clutch = nil end @@ -18,12 +26,23 @@ function Gearbox:linkDiff(diff) end function Gearbox:shift(dir) - + self:setGear(self.gear + dir) end function Gearbox:setGear(gear) if gear >= -1 and gear <= #self.ratios then self.gear = gear + self:recalcRatio() + end +end + +function Gearbox:recalcRatio() + if self.gear == -1 then + self.ratio = -self.reverse + elseif self.gear == 0 then + self.ratio = 0 + else + self.ratio = self.ratios[self.gear] end end @@ -33,5 +52,15 @@ function Gearbox:linkClutch(clutch) end function Gearbox:update() + if self._clutch ~= nil then + self.torque = self._clutch.torque * self.ratio * self.finalDrive + end + local axlesRPM = table.map(self._linkedDiffs, function(diff) + return diff.avgRPM + end) + + local maxAxlesRPM = math.max(unpack(axlesRPM)) + + self.rpm = maxAxlesRPM * self.finalDrive * self.ratio end diff --git a/koptilnya/engine/gearboxes/cvt.txt b/koptilnya/engine/gearboxes/cvt.txt index 020d20b..b82c24a 100644 --- a/koptilnya/engine/gearboxes/cvt.txt +++ b/koptilnya/engine/gearboxes/cvt.txt @@ -1,7 +1,7 @@ -- @include ./base.txt -require("./base.txt") +require('./base.txt') -CVT = class("CVT") +CVT = class('CVT') function CVT:initialize(options) options = options or {} diff --git a/koptilnya/engine/gearboxes/manual.txt b/koptilnya/engine/gearboxes/manual.txt index 2f7da78..d8ef6a6 100644 --- a/koptilnya/engine/gearboxes/manual.txt +++ b/koptilnya/engine/gearboxes/manual.txt @@ -1,17 +1,40 @@ -- @include ./base.txt -require("./base.txt") +require('./base.txt') -ManualGearbox = class("ManualGearbox") +ManualGearbox = class('ManualGearbox') function ManualGearbox:initialize(options) options = options or {} -- might want to segregate construction options for base gearbox self.base = Gearbox:new(options) + self.torque = 0 + self.rpm = 0 + self.gear = 0 + self.ratio = 0 end function ManualGearbox:linkClutch(clutch) return self.base:linkClutch(clutch) end --- proxy the methods here +function ManualGearbox:linkDiff(diff) + return self.base:linkDiff(diff) +end + +function ManualGearbox:shift(dir) + return self.base:shift(dir) +end + +function ManualGearbox:setGear(gear) + return self.base:setGear(gear) +end + +function ManualGearbox:update() + self.base:update() + + self.rpm = self.base.rpm + self.torque = self.base.torque + self.gear = self.base.gear + self.ratio = self.base.ratio +end diff --git a/koptilnya/engine/main.txt b/koptilnya/engine/main.txt index bfa56c4..91c24ba 100644 --- a/koptilnya/engine/main.txt +++ b/koptilnya/engine/main.txt @@ -13,53 +13,100 @@ -- @include ./differential.txt -- -- @include ./configs/audi_tt.txt -require("./engine.txt") +-- @include ../libs/watcher.txt +require('./engine.txt') -- -require("./clutch.txt") +require('./clutch.txt') -- -require("./gearboxes/manual.txt") -require("./gearboxes/cvt.txt") -require("./gearboxes/auto.txt") +require('./gearboxes/manual.txt') +require('./gearboxes/cvt.txt') +require('./gearboxes/auto.txt') -- -require("./differential.txt") +require('./differential.txt') -- -require("./configs/audi_tt.txt") +require('./configs/audi_tt.txt') +require('../libs/watcher.txt') -ECU = class("ECU") +ECU = class('ECU') function ECU:initialize(options) options = options or {} + self:adjustPorts() + self.engine = options.Engine self.clutch = options.Clutch self.gearbox = options.Gearbox self.differentials = options.Differentials - self.input = {} - - self:adjustPorts() + self.input = wire.ports.Input or nil hook.add('tick', 'ecu_update', function() self:update() end) + + self.shifterWatcher = watcher(function() + return self.input.Shifter.Value + end, function(val) + if self.gearbox == nil or val == 0 then + return + end + + self.gearbox:shift(val) + end) end function ECU:adjustPorts() wire.adjustPorts({ - Input = "table" + Input = 'table', + FL = 'entity', + FR = 'entity', + RL = 'entity', + RR = 'entity' }, { - RPM = "number", - Torque = "number" + RPM = 'number', + Torque = 'number', + ClutchTorque = 'number', + ClutchPress = 'number', + AvgRPM = 'number', + GearboxTorque = 'number', + GearboxRPM = 'number', + GearboxRatio = 'number', + Gear = 'number', + ClutchSlip = 'number' }) end function ECU:update() wire.ports.RPM = self.engine.rpm wire.ports.Torque = self.engine.torque + wire.ports.ClutchPress = self.clutch.press + wire.ports.ClutchTorque = self.clutch.torque + wire.ports.ClutchSlip = self.clutch.slip + wire.ports.GearboxTorque = self.gearbox.torque + wire.ports.GearboxRPM = self.gearbox.rpm + wire.ports.AvgRPM = self.differentials[1].avgRPM + wire.ports.Gear = self.gearbox.gear + wire.ports.GearboxRatio = self.gearbox.ratio self.input = wire.ports.Input - self.engine:setThrottle(self.input.Throttle.Value) + if self.input.Throttle then + self.engine:setThrottle(self.input.Throttle.Value) + end + + if self.input.Clutch then + self.clutch:setPress(self.input.Clutch.Value) + end + self.engine:update() + self.clutch:update() + self.gearbox:update() + + self.shifterWatcher() + + for _, diff in ipairs(self.differentials) do + diff:update() + end end local clutch = Clutch:new(config.Clutch) @@ -70,8 +117,19 @@ engine:linkClutch(clutch) local gearbox = ManualGearbox:new(config.Gearbox) gearbox:linkClutch(clutch) +local frontDifferential = Differential:new(config.FrontDiff) +frontDifferential:linkWheels(wire.ports.FL, wire.ports.FR) +frontDifferential:linkGearbox(gearbox) + +local rearDifferential = Differential:new(config.RearDiff) +rearDifferential:linkWheels(wire.ports.RL, wire.ports.RR) +rearDifferential:linkGearbox(gearbox) + +local differentials = {frontDifferential, rearDifferential} + local ecu = ECU:new({ Engine = engine, - Clutch = clutch - -- Gearbox = gearbox + Clutch = clutch, + Differentials = differentials, + Gearbox = gearbox }) diff --git a/koptilnya/engine/modules/launch_control.txt b/koptilnya/engine/modules/launch_control.txt new file mode 100644 index 0000000..e69de29 diff --git a/koptilnya/input_system/cl_input.txt b/koptilnya/input_system/cl_input.txt index 2a2fd91..83a4849 100644 --- a/koptilnya/input_system/cl_input.txt +++ b/koptilnya/input_system/cl_input.txt @@ -27,8 +27,8 @@ function Input:noKeysHolding(axle) end function Input:getAxleValue(axle) - local positiveValue = axle.Positive ~= nil and input.isKeyDown(axle.Positive) - local negativeValue = axle.Negative ~= nil and input.isKeyDown(axle.Negative) + local positiveValue = axle.Positive ~= nil and (input.isKeyDown(axle.Positive) or input.isMouseDown(axle.Positive)) + local negativeValue = axle.Negative ~= nil and (input.isKeyDown(axle.Negative) or input.isMouseDown(axle.Negative)) return (positiveValue and 1 or 0) - (negativeValue and 1 or 0) -- (input.isKeyDown(axle.Positive) and 1 or 0) - (input.isKeyDown(axle.Negative) and 1 or 0) end diff --git a/koptilnya/input_system/configs/sample.txt b/koptilnya/input_system/configs/sample.txt index 7f81768..4dba483 100644 --- a/koptilnya/input_system/configs/sample.txt +++ b/koptilnya/input_system/configs/sample.txt @@ -7,7 +7,18 @@ Axles = { }, Throttle = { Positive = KEY.W, + Gravity = 1, + Sensitivity = 1 + }, + Clutch = { + Positive = KEY.SHIFT, Gravity = 0.15, - Sensitivity = 0.2 - } + Sensitivity = 0.25 + }, + Shifter = { + Positive = MOUSE.LEFT, + Negative = MOUSE.RIGHT, + Gravity = 1, + Sensitivity = 1 + }, } diff --git a/koptilnya/input_system/main.txt b/koptilnya/input_system/main.txt index 8f7db81..319bd06 100644 --- a/koptilnya/input_system/main.txt +++ b/koptilnya/input_system/main.txt @@ -21,3 +21,11 @@ local input = Input:new(options) hook.add('tick', 'InputUpdate', function() input:update() end) + +if SERVER then + hook.add('input', 'wire_input_update', function(key, value) + if key == 'Seat' then + input:updateSeat() + end + end) +end diff --git a/koptilnya/input_system/sv_input.txt b/koptilnya/input_system/sv_input.txt index 8629dca..555e673 100644 --- a/koptilnya/input_system/sv_input.txt +++ b/koptilnya/input_system/sv_input.txt @@ -104,13 +104,18 @@ function Input:initialize(options) self:_setupAxles(axles) - self.seat = wire.ports.Seat + self:updateSeat() + self.driver = self:getDriver() -- in case chip was reset self:_syncDriver(self.driver) end +function Input:updateSeat() + self.seat = wire.ports.Seat or NULL_ENTITY +end + function Input:getDriver() if self.seat == nil or self.seat:isValid() == false then return NULL_ENTITY diff --git a/koptilnya/libs/table.txt b/koptilnya/libs/table.txt index b34c250..064db6b 100644 --- a/koptilnya/libs/table.txt +++ b/koptilnya/libs/table.txt @@ -93,3 +93,15 @@ function table.find(tbl, predicate) end end end + +function table.reduce(tbl, func, init) + init = init or 0 + + local accum = init + + for _, field in ipairs(tbl) do + accum = accum + func(field) + end + + return accum +end diff --git a/koptilnya/libs/watcher.txt b/koptilnya/libs/watcher.txt new file mode 100644 index 0000000..41dc47e --- /dev/null +++ b/koptilnya/libs/watcher.txt @@ -0,0 +1,14 @@ +function watcher(expr, cbk) + local lastVal = expr() + + return function() + local newVal = expr() + + if newVal == lastVal then + return + end + + cbk(newVal, lastVal) + lastVal = newVal + end +end